Tuesday, 05 August 2008

The EFDesign team is giving you a platform to discuss the way they are planning to implement POCO into EF. This is the time to be heard, so click here.
I have been spending my energy on my upcoming international move and silverlight, but it’s an interesting post that I will be following with great interest!

Tuesday, 05 August 2008 15:23:46 (Romance Standard Time, UTC+01:00)  #    Comments [8]  |  Trackback
 Friday, 25 July 2008

I started my career when I was still in university. I started a company named Sitechno that did webapplications and custom solutions. The last few years, I’ve been hired as a consultant on some big projects.
The role I was given on my last project, allowed me to do some crazy cool stuff, using nHibernate and winforms. I was able to push WCF, WF and WPF into a big client/server application, and had great success with it. We reformed a monolithic data-oriented application into a domain-oriented loosely coupled application.

It’s easy enough to find new projects, but the market for the cutting edge technologies is not very big ;-)

When I was asked to join Microsoft, my main attraction to the offer was the opportunity to work on cutting edge technology with a group of passionate people. When I talked Microsofties on the Redmond campus, it became clear that they could certainly offer just that.

I was torn between working on EF (which, I’ve been very involved with lately) and on Silverlight.
In the end, Silverlight won, because I strongly believe it to be the strongest contender in the client space, there is an interesting ‘war’ going on right now, and I have really enjoyed working with the WPF-framework in the past. I was torn by the decision because whatever choice I made, I knew that a great opportunity would be lost.

We will be heading to Vancouver, Canada in September and I will work for Microsoft Canada for a year. After that, I will be allowed to work in the U.S.A. and we will move to Redmond.

You can not believe how excited I am about this opportunity. I will be working for Shawn Burke on Silverlight Controls. I’m not sure yet who else is working on the team, but I believe/hope I’ll be working with David, Ted, Kirti and Jeff.

As for EFContrib: although I’m dedicated to it, I’m having a hard time finding the time to work on it. Also, since version 2.0 of EF will feature some nice Poco capabilities. So, I’m not sure if people are waiting for the solution. It would be nice to make it work with SL though! So, if I find the time, or get lots of mail of people wanting me to finish it properly, I’ll work on it some more.

Friday, 25 July 2008 09:46:13 (Romance Standard Time, UTC+01:00)  #    Comments [15]  |  Trackback
 Wednesday, 16 April 2008

I just finished a small sample application that illustrates a client/server application using Entity Framework on the server and just regular objects on the client. The client has custom changetracking and the server is able to attach the graph to a context again. Source can be found at the efcontrib page, and I guess I'm almost ready to do a proper release!

[I used Prism to build the client in a Model View Controller approach. It was a fun exercise and I'm looking forward to seeing that project released.]

The application manages employees and allows for setting a 'teamleader' on an employee: think of 'is managed by'. I thought it would be cool to send that over the wire.

Here is a screenshot of the main view of the application:

image

As you can see, you can 'choose' an employee. When you press that button, you will see another screen where you can enter a lastname. It will fill a grid with employees matching that criteria and allows you to choose from that list.
It is also allowed to 'add an employee'. There are actually 3 types of employees you can add: Mort, Elvis and Einstein.

On the row of teamleader, you can again press the 'choose' button, which will allow you to set a relation between the employee you are editing and another employee.

On the server, there are a few methods like this:

  0   public List<Employee> GetEmployees(string lastNameBeginsWith)
  1   {
  2    using (InheritanceTypeContext context = new InheritanceTypeContext())
  3    {
  4
  5     List<Employee> employees = (from e in context.Person.OfType<Employee>().Include("TeamLeader").Include("TeamMembers")
  6       where e.Lastname.StartsWith(lastNameBeginsWith)
  7       select e).ToList();
  8
  9    
  10     employees.ForEach(p => context.PrepareForSerialization(p)) ;
  11     return employees;
  12    }
  13   }
  14

 

You can see me taking care to call the 'prepareForSerialization' on each graph that I'm returning on line 10.

The client can just use these objects like normal.

 

I'll look into delving into it a bit with a screencast soon.

Wednesday, 16 April 2008 14:55:10 (Romance Standard Time, UTC+01:00)  #    Comments [6]  |  Trackback

I first wanted to focus on the other aspects of EFContrib, but I finally sat down and finished the last missing piece of EFContrib: full inheritance support for both the server bits and the client bits.

Most work was in the serialization actually, since the surrogate classes need to now also serialize the properties of base types.

I'm working on a sample right now that will show off the system in WPF. But you can check out some of the code in the test project.
This is the domain I'm using:

image

In the following code I'm using it.

  0    using (InheritanceTypeConnection context = new InheritanceTypeConnection())
  1    {
  2     var persons = from p in context.Person
  3          select p;
  4     foreach (Person p in persons)
  5      context.DeleteObject(p);
  6
  7     context.SaveChanges();
  8    }
  9
  10    string MsgOnWire = String.Empty;
  11    int id;
  12    using (InheritanceTypeConnection context = new InheritanceTypeConnection())
  13    {
  14
  15     Einstein lead = new Einstein { Firstname = "Bill", Lastname = "G" };
  16     context.AddToPerson(lead);
  17
  18     Mort e1 = new Mort { Firstname = "Ruurd", Lastname = "Boeke", Language = "C#", EF=true, WCF=true, WF= true, WPF=true, TeamLeader=lead };
  19     context.AddToPerson(e1);
  20
  21     Elvis e2 = new Elvis { Firstname = "Elvis", Lastname = "Presley", Language = "Java", EF = false, WCF = true, WF = false, WPF = true, TeamLeader = lead };
  22     context.AddToPerson(e2);
  23
  24     context.SaveChanges();
  25     id = e1.PersonID;
  26
  27     MsgOnWire = context.Serialize(e1);  // we'll take mort as the graphroot (no importance)
  28    }
  29
  30    // deserialize
  31    MortClient mClient = MsgOnWire.DeserializeForClient<MortClient>();
  32    mClient.Firstname = "changedAt" + DateTime.Now.ToString();
  33    string nameToCheck = mClient.Firstname;
  34    mClient.EF = false; // mort tends to forget skills
  35
  36    EmployeeClient teamlead = mClient.TeamLeader;
  37
  38    // elvis is a free soul, he can not be managed.
  39    ElvisClient eClient = (ElvisClient) mClient.TeamLeader.TeamMembers.Last();
  40    mClient.TeamLeader.TeamMembers.Remove(eClient);
  41    eClient.TeamLeader = null;
  42
  43    // always add more einsteins in the mix
  44    EinsteinClient einClient = new EinsteinClient { EF = true, WCF = true, WF = false, WPF = false, TeamLeader = teamlead, Firstname = "Albert", Language = "C#", Lastname = "Einstein" };
  45    teamlead.TeamMembers.Add(einClient);
  46
  47
  48    // serialize
  49    MsgOnWire = mClient.SerializeForClient();
  50
  51
  52    using (InheritanceTypeConnection context = new InheritanceTypeConnection())
  53    {
  54
  55     // deserialize
  56     Mort m = context.Deserialize<Mort>(MsgOnWire);
  57
  58     context.SaveChanges();
  59    }
  60

Lines 31 to 41 represent the client. For testing purposes I created a copy of the domain with the suffix Client. In normal usage this would obviously not be necessary.
The client remembers all the original values, which allows the server to build up an efficient graph when it is time to attach.

Wednesday, 16 April 2008 11:18:32 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Monday, 07 April 2008

I have just checked in a sample application that uses a server to retrieve data with EF and a client that is totally unaware of EF. Changes on the client are changetracked and serialized in a pretty xml format. Then, the server attaches to the graph and is able to use a context to save changes.
In this post I will explain some of the parts in more detail. I hope to follow up on some point with a screencast. First, let's take a step back and look at the problem (skip this if you've read my blog lately).

Problems with N-Tier EF

Normal Entity Framework usage will generate classes for you that are adorned with [DataMember] attributes, making them serializable using WCF's DataContractSerializer.
The class that was generated has intimate knowledge of Entity Framework, which presents itself as EF-specific tags in the XML: not pretty and not SOA at all!

Further, on the receiving end (the client that deserializes these objects) those same classes need to be around to deserialize into. This means that you will have to use Entity Framework on the client: not SOA at all. This pretty much limits the usage of your domain objects to a .Net client. (I'm not sure if Silverlight will be able to use EF. If not: you will not be able to use these objects in Silverlight as well)

I probably pointed to this post before, but Daniel Simmons talks about using EF in your architecture. He acknowledges the problem but does not see it as a very big issue. In some situations, this might not be a big problem, but in others it is.

Then, there is the issue of serializing the objects with all their relations in-tact. It's harder than you would hope. Daniel again has a solution, that you can find here. He basically creates a serializable class (EntityBag) which groups all relations and objects together and knows how to reassemble them. This way you can use your objects on the client using EF and have a pretty seamless experience. Great!! However, it's not going to work for other client technologies, so forget about SOA.

Also: I prefer to work in a more 'agile'/'domain driven' way. Having a layer manifest itself all the way up to the client, where it does not belong, really kills flexibility.

Solution scope

My aim is to provide a solution that will allow me to:

  1. Work with POCO classes (as persistence ignorant as I can get)
  2. No EF references on the client
  3. Full changetracking on the client that can be attached easily
  4. Use the same Domain classes (with it's logic and validation rules) on both server and client: so no duplication of code

We should be able to work with our classes in Silverlight even.

The Parts of the Solution

I have partitioned the solution into some smaller projects. All use PostSharp to do it's magic, but you will not notice a thing about it. (If you are unaware: PostSharp will perform a step after compilation to transform your IL. This way, no source code pollution).

POCO  (only on server):

  1. this project will enrich your domain objects with EF information, so there is no need to litter your objects with EF specific. Feel the agile love.
  2. has the ability to provide 'original values' to the serializer
  3. has the ability/knowledge on how to attach a graph to an EF context

Circular serializer (both on server as client):

  1. creates surrogate objects that will be stand-ins during serialization. This fixes the circular serialization problem.
  2. also creates datamembers that will hold your original values during serialization
  3. creates a method (CopyFromSurrogate) that allows the serializer to fill the original object with values from the surrogate.

The circular serializer does more then just solve the circular serialization problem. I might refactor this to make it clearer.

Editable Business Object (only on client):

  1. this project implements IEditableObject (and INotifyPropertyChanged) on your domain object
  2. knows how to keep 'original values' and provide them to the serializer

Again, this project might be split.

 

So there are 3 different parts here. Let's look at that with a picture:

image

Basically, the circular serializer is the glue that is used on both the server and the client. It knows how to serialize your objects and asks for help to get to the original values. On the client, the EditableBusinessObject can provide that, on the server, it is the original POCO project.

Using them is dead simple, as I'll show.

Look at some code

I've used the School database and let EF generate the entity mappings. I did not change anything from the defaults, which basically means that the classes we end up with are pretty awful. I don't care about them though for this sample.

image

I then set the generated code to 'not compile' and created the following beautiful classes by hand:

  0 namespace Domain
  1 {
  2 [DataContract(Name = "Person", Namespace = "tstNS")]
  3  public class Person
  4 {
  5   [DataMember]
  6   public int PersonID { get; set; }
  7   [DataMember]
  8   public string LastName { get; set; }
  9   [DataMember]
  10   public string FirstName { get; set; }
  11   [DataMember]
  12   public DateTime? HireDate { get; set; }
  13   [DataMember]
  14   public DateTime? EnrollmentDate { get; set; }
  15
  16   [DataMember]
  17   public ICollection<Enrollment> Enrollments { get; set; }
  18   [DataMember]
  19   public ICollection<Course> Courses { get; set; }
  20
  21 }
  22
  23 [DataContract(Name = "Course", Namespace = "tstNS")]
  24  public class Course
  25 {
  26   [DataMember]
  27   public int CourseID { get; set; }
  28   [DataMember]
  29   public string Title { get; set; }
  30   [DataMember]
  31   public string Days { get; set; }
  32   [DataMember]
  33   public DateTime Time { get; set; }
  34   [DataMember]
  35   public string Location { get; set; }
  36   [DataMember]
  37   public int Credits { get; set; }
  38   [DataMember]
  39   public Department Department { get; set; }
  40
  41   [DataMember]
  42   public ICollection<Enrollment> Enrollments { get; set; }
  43   [DataMember]
  44   public ICollection<Person> Persons { get; set; }
  45
  46 }
  47 [DataContract(Name="Department", Namespace="tstNS")]
  48  public class Department
  49 {
  50   [DataMember]
  51   public int DepartmentID { get; set; }
  52   [DataMember]
  53   public string Name { get; set; }
  54   [DataMember]
  55   public Decimal Budget { get; set; }
  56   [DataMember]
  57   public DateTime StartDate { get; set; }
  58   [DataMember]
  59   public int Administrator { get; set; }
  60
  61   [DataMember]
  62   public ICollection<Course> Courses { get; set; }
  63
  64 }
  65 [DataContract(Name = "Enrollment", Namespace = "tstNS")]
  66  public class Enrollment
  67 {
  68   [DataMember]
  69   public int EnrollmentID { get; set; }
  70   [DataMember]
  71   public Decimal? Grade { get; set; }
  72
  73   [DataMember]
  74   public Course Course { get; set; }
  75   [DataMember]
  76   public Person Person { get; set; }
  77
  78 }
  79 }
  80

Now, I need a trick to get seperate versions of this on the client and the server. I altered the msbuild script to add a conditional compile symbol that is the name of the solution. You could go fancy with this technique, by matching the build name and stuff. I just used this:

  <PropertyGroup>
    <DefineConstants>$(DefineConstants);$(SolutionName)</DefineConstants>
</PropertyGroup>

(Please let me know when someone uses this technique to target both Silverlight and regular .net. It's possible!)
So, now it's time to apply our postsharp attributes. I did that in the assembly info file:

#if Server
[assembly: Poco("SchoolEntitiesConnection", AttributeTargetAssemblies = "Domain", AttributeTargetTypes = "Domain.*")]
[assembly: CreateSerializeSurrogate("EntityFrameworkContrib.PostSharp4EF.ISerializationHelp, EntityFrameworkContrib.PostSharp4EF", AttributeTargetAssemblies = "Domain", AttributeTargetTypes = "Domain.*")]
#endif
#if Client
[assembly: EditableBusinessObjectAttribute(AttributeTargetAssemblies="Domain", AttributeTargetTypes="Domain.*")]
[assembly: CreateSerializeSurrogate("EditableBusinessObjects.Postsharp.Public.IEditableBusinessObject, EditableBusinessObjects.Postsharp.Public", AttributeTargetAssemblies="Domain", AttributeTargetTypes="Domain.*")]
#endif

Pretty neat, isn't it? This notifies postsharp to either use Poco or EditableBusinessObject to modify the compiled code. I only have one place to maintain this code.
As you can see, the circular serialize (CreateSerializeSurrogate) takes the name of a type that it can use to get 'original value' information from.

I also created an interface project (just a nice best-practice) to identify my operation contract:

  0 [CircularReferenceSurrogateAttribute]
  1 [ServiceContract(Namespace="Http://sitechno.School")]
  2  public interface ISchoolService
  3 {
  4   [OperationContract]
  5   Person GetPerson(int id, bool fetchEnrollments, bool fetchCourses);
  6
  7   [OperationContract]
  8   void SavePerson(Person person);
  9
  10   [OperationContract]
  11   IList<Course> GetCourses();
  12
  13   [OperationContract]
  14   IList<Department> GetDepartments();
  15
  16 }

See the CircularReferenceSurrogateAttribute on line 0: it applies a datacontract surrogate manager, that will substitute surrogate types for the real types during serialization.

Now, for the server:

  0  public class SchoolService : ISchoolService
  1 {
  2   public Person GetPerson(int id, bool fetchEnrollments, bool fetchCourses)
  3   {
  4    using (SchoolContext context = new SchoolContext())
  5    {
  6     Person p = (from person in context.Person
  7        where person.PersonID  == id
  8           select person).First();
  9
  10     if (fetchEnrollments)
  11     {
  12      ((IRelationshipLoader)p).Load("Enrollments");
  13      foreach (Enrollment r in p.Enrollments)
  14      {
  15       ((IRelationshipLoader)r).Load("Course");
  16       ((IRelationshipLoader)r).Load("Person");
  17      }
  18     }
  19    
  20     if (fetchCourses)
  21     {
  22      ((IRelationshipLoader)p).Load("Courses");
  23      foreach (Course c in p.Courses)
  24      {
  25       ((IRelationshipLoader)c).Load("Department");
  26       ((IRelationshipLoader)c).Load("Enrollments");
  27       ((IRelationshipLoader)c).Load("Persons");
  28
  29      }
  30     }
  31
  32     ((IContextAware)p).CreateSerializableState(context);
  33
  34     return p;
  35    }
  36
  37   }
  38
  39
  40   public void SavePerson(Person person)
  41   {
  42    using (SchoolContext context = new SchoolContext())
  43    {
  44     ((IContextAware)person).AttachGraphToContext(context, entity => entity.GetType().Name);
  45
  46     context.SaveChanges();
  47    }
  48   }
  49
  50
  51   public IList<Course> GetCourses()
  52   {
  53    using (SchoolContext context = new SchoolContext())
  54    {
  55     List<Course> courses = context.Course.ToList();
  56     courses.ForEach(crs => ((IContextAware)crs).CreateSerializableState(context));
  57     return courses;
  58
  59    }
  60   }
  61
  62   public IList<Department> GetDepartments()
  63   {
  64    using (SchoolContext context = new SchoolContext())
  65    {
  66     List<Department> deps = context.Department.ToList();
  67     deps.ForEach(dp => ((IContextAware)dp).CreateSerializableState(context));
  68     return deps;
  69    }
  70   }
  71
  72 }

Before someone tells me that I'm not doing the includes/spans correctly in the GetPerson method: I'll do it better when I do a more complete sample.

As you can see, for methods that return classes, I call the CreateSerializableState method. Methods that accept a graph have to call the AttachGraphToContext method. Obviously, these can and should be context extensibility methods.

  • The CreateSerializableState method will use the context to get the 'original' values and load them into your object. Your class actually has fields to hold this information (as created by Poco).
  • The AttachGraphToContext method is quite complex and will look at a graph and it's original values. It will first set the original values, than do an acceptchanges and change only those properties that were actually changed. It also fixes up relationships, using add/attach/delete.

The client:

  0   static void Main(string[] args)
  1   {
  2    SchoolService svc = new SchoolService();
  3
  4    IList<Department> departments = svc.GetDepartments();
  5
  6    Person Fadi = svc.GetPerson(4, false, false);
  7
  8    Console.WriteLine(String.Format("Working on {0} {1}, Hired at {2:D}",
  9     Fadi.FirstName, Fadi.LastName, Fadi.HireDate));
  10    Console.WriteLine();
  11
  12    Console.WriteLine("The ID is not generated by the database in this instance, so please give me a number that is not used already");
  13    int id = Int32.Parse(Console.ReadLine());
  14
  15    Console.WriteLine("I can bug you for a title as well, can't I?");
  16    string title = Console.ReadLine();
  17
  18    Course newCourse = new Course { CourseID = id, Credits = 10, Days = "MT", Time = DateTime.Now, Title = title };
  19    newCourse.Persons = new List<Person> { Fadi }; // normally, your object ctor would have done this
  20    newCourse.Enrollments = new List<Enrollment>();
  21    newCourse.Department = departments.First();
  22    newCourse.Department.Courses.Add(newCourse);
  23
  24    Fadi.FirstName = "Fadi,Changed at " + DateTime.Now.ToShortTimeString();
  25
  26
  27    Fadi.Courses.Add(newCourse);
  28
  29
  30    svc.SavePerson(Fadi);
  31
  32    Console.WriteLine("Finished, go check your database. I added the new course to department:" + newCourse.Department.Name);
  33    Console.ReadLine();
  34
  35
  36   }

One important thing to know is that on the client, there is no longer a concept of relations, only lists. So you will need to hook up classes from both angles when you connect them: see lines 21 and 22.

Things to note
  • There is a LOT going on, but you are shielded from it and can work in a blissful persistence ignorance way!
  • Your objects will implement quite a few interfaces that you can use if you'd like
  • The client side implements INotifyPropertyChanged (and raises events correctly) but the ICollection implementations are still just Lists<>. I will change that to ObservableCollections for you WPF lovers! (which includes me)
  • I have not implemented deleting yet. So you can unhook a relationship, but that does not delete the object. I don't think that it should either! I will probably implement some 'MarkAsDelete' method on the client-side
  • There is a strong optimization for speed. I, for instance, generate a method 'SetValue(string propname, object val)' and corresponding GetValue so that the framework does not need to use reflection or dynamic method generation. Still, I haven't covered everything yet, so there is still some expensive reflection going on. The overall goal is certainly to reduce this to null.
  • This is not a version 1.0 release. Do not treat it as such. It's complex matter, and some things are not supported yet. Still 98% is finished.
  • I rushed the samples. There is a wpf sample that has the worst codebehind that exists. Do not open it, your eyes will hurt. When I have time I'll build a proper MVC sample that actually doesn't crash.

I am very excited to have gotten this far. Since PostSharp supports Silverlight, I'll try to get this to work for silverlight as well, so we can build some serious RIA's! I'll try to follow up with a screen cast soon.

kick it on DotNetKicks.com

Monday, 07 April 2008 21:25:31 (Romance Standard Time, UTC+01:00)  #    Comments [5]  |  Trackback
 Wednesday, 02 April 2008

I have had my problems with the EF designer for some time now, but Noam Ben-Ami talks about the improvements that are being made in the next drop here.

They seem to have fixed a lot of issues with the update-from-database option, which should make it a lot more useful. Cool!

Wednesday, 02 April 2008 10:07:46 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Thursday, 27 March 2008

[important: this post belongs to a whole host of other posts. Basically it's about my efforts of building a light-weight n-tier disconnected solution for Entity Framework]

Another status update. I've worked on connecting up a clean graph to a EntityFramework context and found it far from straight-forward! I ended up with very little code though, which is a good sign.

The approach of not serializing the object context, makes it harder to figure out when an object was added or removed. On the client, I keep copies of the 'original' collection and I compare the new collection with the old collection. Problem there is that it's quite possible that an object was just removed from a collection and added to another collection. How do we know we have to do a real 'delete' on it?
I have not yet figured this out ;-)

Here is some code for you to look at:

  0    Customer c = new Customer { Name = "Ruurd Boeke" };
  1    Car car1 = new Car { Make = "Saab", Customer = c };
  2    Order order1 = new Order { Amount = 2, Customer = c };
  3
  4
  5    IEditableBusinessObject eC = c as IEditableBusinessObject;
  6    string MsgOnWire = "";
  7
  8    // at this point, we are not at all attached
  9    using (SimpleRelationshipTestEntities context = new SimpleRelationshipTestEntities())
  10    {
  11     context.AddToCustomer(c);
  12     context.SaveChanges();  // this instructs context to start changetracking
  13
  14     ((IContextAware)c).CreateSerializableState(context);
  15
  16     DataContractSerializer s = new DataContractSerializer(c.GetType(), null, int.MaxValue, false, false, new SubstituteDomainDataContractSurrogate());
  17
  18     MsgOnWire = s.GetWellFormedToContract(c);
  19    }
  20

The message on the wire looks like this:

<CustomerSurrogate xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="myNamespace">
    <Cars>
        <Car>
            <CarID>244</CarID>
            <Customer>
                <SerializationID>0</SerializationID>
            </Customer>
            <Make>Saab</Make>
            <SerializationID>1</SerializationID>
            <OriginalValue_CarID>244</OriginalValue_CarID>
            <OriginalValue_Customer>
                <SerializationID>0</SerializationID>
            </OriginalValue_Customer>
            <OriginalValue_Make>Saab</OriginalValue_Make>
        </Car>
    </Cars>
    <CustomerID>152</CustomerID>
    <Name>Ruurd Boeke</Name>
    <Orders>
        <Order>
            <Amount>2</Amount>
            <Customer>
                <SerializationID>0</SerializationID>
            </Customer>
            <OrderID>159</OrderID>
            <SerializationID>2</SerializationID>
            <OriginalValue_Amount>2</OriginalValue_Amount>
            <OriginalValue_Customer>
                <SerializationID>0</SerializationID>
            </OriginalValue_Customer>
            <OriginalValue_OrderID>159</OriginalValue_OrderID>
        </Order>
    </Orders>
    <SerializationID>0</SerializationID>
    <OriginalValue_Cars>
        <Car>
            <SerializationID>1</SerializationID>
        </Car>
    </OriginalValue_Cars>
    <OriginalValue_CustomerID>152</OriginalValue_CustomerID>
    <OriginalValue_Name>Ruurd Boeke</OriginalValue_Name>
    <OriginalValue_Orders>
        <Order>
            <SerializationID>2</SerializationID>
        </Order>
    </OriginalValue_Orders>
</CustomerSurrogate>

Next step is to receive this xml on the client, deserialize it and change some stuff:

  0    DataContractSerializer s2 = new DataContractSerializer(typeof(CustomerClient), null, int.MaxValue, false, false, new SubstituteDomainDataContractSurrogate());
  1    CustomerClient c2 = (CustomerClient)s2.UnwrapFromString(MsgOnWire);
  2
  3    // delete
  4    c2.Cars.First().Customer = null;
  5    c2.Cars.Clear();
  6
  7    // add
  8    OrderClient order2 = new OrderClient { Amount = 100, Customer = c2 };
  9    c2.Orders.Add(order2);
  10
  11    // change
  12    c2.Name = "Changed";
  13
  14    // we have edited everything, let's get back to the server
  15    DataContractSerializer s3 = new DataContractSerializer(typeof(CustomerClient), null, int.MaxValue, false, false, new SubstituteDomainDataContractSurrogate());
  16    MsgOnWire = s3.GetWellFormedToContract(c2);

This client is removing the cars. Note that we do not get the automatic hookup of relations that we used to get on the server: there is no EF Relationship manager on the client!

<CustomerSurrogate xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="myNamespace">
    <Cars />
    <CustomerID>152</CustomerID>
    <Name>Changed</Name>
    <Orders>
        <Order>
            <Amount>2</Amount>
            <Customer>
                <SerializationID>0</SerializationID>
            </Customer>
            <OrderID>159</OrderID>
            <SerializationID>1</SerializationID>
            <OriginalValue_Amount>2</OriginalValue_Amount>
            <OriginalValue_Customer>
                <SerializationID>0</SerializationID>
            </OriginalValue_Customer>
            <OriginalValue_OrderID>159</OriginalValue_OrderID>
        </Order>
        <Order>
            <Amount>100</Amount>
            <Customer>
                <SerializationID>0</SerializationID>
            </Customer>
            <SerializationID>2</SerializationID>
        </Order>
    </Orders>
    <SerializationID>0</SerializationID>
    <OriginalValue_Cars>
        <Car>
            <CarID>244</CarID>
            <Make>Saab</Make>
            <SerializationID>3</SerializationID>
            <OriginalValue_CarID>244</OriginalValue_CarID>
            <OriginalValue_Customer>
                <SerializationID>0</SerializationID>
            </OriginalValue_Customer>
            <OriginalValue_Make>Saab</OriginalValue_Make>
        </Car>
    </OriginalValue_Cars>
    <OriginalValue_CustomerID>152</OriginalValue_CustomerID>
    <OriginalValue_Name>Ruurd Boeke</OriginalValue_Name>
    <OriginalValue_Orders>
        <Order>
            <SerializationID>1</SerializationID>
        </Order>
    </OriginalValue_Orders>
</CustomerSurrogate>

We see that there are no current cars, but the original value of cars still has them. That is how I figure out to delete the cars on the server.
Did you also notice how the new order does not have a ID assigned? The server will take care of it.

  0    // we're at the server
  1    using (SimpleRelationshipTestEntities context = new SimpleRelationshipTestEntities())
  2    {
  3     DataContractSerializer s4 = new DataContractSerializer(typeof(Customer), null, int.MaxValue, false, false, new SubstituteDomainDataContractSurrogate());
  4     Customer c3 = (Customer)s4.UnwrapFromString(MsgOnWire);
  5
  6     ((IContextAware)c3).AttachGraphToContext(context,
  7      delegate(object source)
  8      {
  9       return source.GetType().Name;   // our setnames correspond to our classname.
  10      });
  11
  12
  13     context.SaveChanges();
  14    }

Now, we're deserializing and attaching the graph to the context. The delete on line 7 is a way of returning entitysetnames. EF needs to know the entitysetname to be able to attach an object to a context, but there is no way for me to know it. So at this point I let you make the decision yourself.

The database is correctly filled and we are happy.

Now, I really want to check in this source, but there is a lot to be done still. The API I have created is monstrous.
Also, I think there are quite a few situations where this will break horribly.

Once I get just a little happier about it, I will do a screencast building a server using Entity Framework and a silverlight client that is editing.

Thursday, 27 March 2008 17:20:28 (Romance Standard Time, UTC+01:00)  #    Comments [10]  |  Trackback
 Monday, 24 March 2008

Found through Julie's blog: a new tool was released on Code Gallery from the EF Team, called EF Mapping Helper.

It will help you play around with mappings and see what the result would be in the corresponding CSDL, SSDL and MSL generated xml.

Read more on Julie's blog and quickly download the tool!

Monday, 24 March 2008 17:08:14 (Romance Standard Time, UTC+01:00)  #    Comments [12]  |  Trackback
 Friday, 21 March 2008

I'm working hard on bringing a couple of my projects together that will enable domainobjects on the client without Entity Framework references. I thought I'd give a small update on how that's working out for me.

The endresult

What I want is one visual studio project: 'Domain' that holds business objects for me that I can use on both the client and the server. What I do not want, is to have to think about EntityFramework contexts on the client. Since I do not persist my objects on the client, I see no reason to actually create a context on the client, just to be able to do changetracking. Nor do I want to see any EF specific plumbing in the messages between that client and server: I lose interoperability if I do that. Also, if my client is Silverlight (for instance) I might not want to bring the EF assemblies over (if that's even possible?).

So, the endresult should be an easy way to serialize and deserialize objects on the client and server, and a way to build up the object correctly on the server so it can be attached to the context again.

Please check Daniel's EntityBag sample for a very sophisticated way of serializing your context. He does go down the route of serializing the objectcontext, which does mean you need the entityframework on the client. Read about his motivations for doing this here.

Let's see it

I'll first show some code and then walk you through it.

  0    using (OneSimpleType.OneSimpleTypeConnection context = new OneSimpleType.OneSimpleTypeConnection())
  1    {
  2     // clear out database
  3     foreach (OneSimpleType.Person old in context.Person)
  4     {
  5      context.DeleteObject(old);
  6     }
  7     context.SaveChanges();
  8    }
  9
  10    OneSimpleType.Person p = new OneSimpleType.Person { Firstname = "Ruurd", Lastname = "Boeke" };
  11    IEditableBusinessObject ep = p as IEditableBusinessObject;
  12    string MsgOnWire = "";
  13
  14    using (OneSimpleType.OneSimpleTypeConnection context = new OneSimpleType.OneSimpleTypeConnection())
  15    {
  16     context.AddToPerson(p);
  17     context.SaveChanges();  // at this point, there should be 'original values'
  18
  19     // the server is changing the object without yet saving
  20     p.Firstname = "ServerChanged";
  21
  22     // now we need to create a version of the object that can be serialized well
  23     p = (OneSimpleType.Person)context.CreateSerializableVersion(p);
  24
  25     DataContractSerializer s = new DataContractSerializer(p.GetType(), null, int.MaxValue, false, false, new SubstituteDomainDataContractSurrogate());
  26
  27     MsgOnWire = GetWellFormedToContract(p, s);
  28
  29    }
  30
  31    // imagine we are the client getting a message and deserializing it
  32    DataContractSerializer s2 = new DataContractSerializer(typeof(OneSimpleType.Person), null, int.MaxValue, false, false, new SubstituteDomainDataContractSurrogate());
  33    StringReader reader = new StringReader(MsgOnWire);
  34    XmlReader xreader = XmlReader.Create(reader);
  35    OneSimpleType.Person p2 = (OneSimpleType.Person)s2.ReadObject(xreader);
  36
  37    // edit something on the client
  38    p2.Lastname = "ClientChanged";
  39
  40
  41    // we have edited everything, let's get back to the server
  42    s2 = new DataContractSerializer(typeof(OneSimpleType.Person), null, int.MaxValue, false, false, new SubstituteDomainDataContractSurrogate());
  43    MsgOnWire = GetWellFormedToContract(p2, s2);
  44
  45    // we're at the server
  46    using (OneSimpleType.OneSimpleTypeConnection context = new OneSimpleType.OneSimpleTypeConnection())
  47    {
  48     DataContractSerializer s3 = new DataContractSerializer(typeof(OneSimpleType.Person), null, int.MaxValue, false, false, new SubstituteDomainDataContractSurrogate());
  49     StringReader reader3 = new StringReader(MsgOnWire);
  50     XmlReader xreader3 = XmlReader.Create(reader3);
  51     OneSimpleType.Person p3 = (OneSimpleType.Person)s3.ReadObject(xreader3);
  52
  53     context.AttachedDeserializedVersion(p3, "Person");
  54
  55     context.SaveChanges();
  56    }
  57

We start out on the serverside.
On line 17, we have just saved an object to the database. 
We continue using that (attached, and thus changetracked) object and change a property (just for the fun of it).
On line 27 we serialize it like you've seen me do in previous posts.

On line 32, we pretend to be on the client, which uses the message to deserialize to a compatible type. Note, that this type does not need to be 'IPoco' enhanced. It does need to be enhanced for serialization and editing.

We change a property 'on the client' on line 38. Notice that this object does not have a context attached at all.
At line 43 we have once again serialized this new object and on line 46 we pretend to be on the server again.

There we create a new context and deserialize our message to an object. Then we call an extension method of context to attach this version to the context. Note that I have to pass the setname (working on somehow getting to this information differently).
Finally we save.

Only the changed properties are flagged as dirty, so efficient SQL can be generated by EF.

The extension method is shown here:

  0   public static void AttachedDeserializedVersion(this ObjectContext context, object source, string setname)
  1   {
  2    // TODO: how to get setname from metadata or something
  3
  4    Debug.Assert(source is IEntityWithKey);
  5    Debug.Assert(source is IEditableBusinessObject);
  6
  7    IEditableBusinessObject eS = (IEditableBusinessObject)source;
  8
  9    // we go to the loaded state
  10    eS.SetReadMode(ReadMode.Loaded);
  11
  14    string fullEntitySetName = context.DefaultContainerName + "." + setname;
  15
  16    EntityKey createdKey = context.GetEntityKey(fullEntitySetName, source);
  17    ((IEntityWithKey)source).EntityKey = createdKey;
  18
  19    // attach this version
  20    context.Attach((IEntityWithKey)source);
  21
  22    eS.ReplayLoadedToNormal();
  23
  24    eS.SetReadMode(ReadMode.Normal);
  25
  26
  27   }

You see I have quite a bit of functionality in the IEditableBusinessObject interface.

The deserialized version of the object has a 'loaded' state (or better: original state) and a 'current' state. Before attaching at line 20, I first set my object to be in 'original' mode. Then I have a replay method that will compare the current values to the loaded versions and touch the setters of the properties of the changed versions. This notifies the changetracker of EF to flag a property as dirty.

This all works fine, but both code and api are pretty crude. I have no complextype or relationshiptype support, but that will come, if I don't run into major problems along the way.

I hope you are as excited about this as I am. Let me know!

Friday, 21 March 2008 18:21:28 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback
 Sunday, 16 March 2008

[update: I've updated my project quite a bit, and moved the state to another object. So, the code you are about to see is old!]

In the grand scheme of things, I'm building toward a set of tools that will enable me to use EntityFramework on the server and use the same businessobjects on the client-side, without having to reference EntityFramework at all.
We already have a great domain layer supporting EF, without baseclasses. To use these objects on the client, we will need to take care of changetracking ourselves. When we are done with that, we'll just have to write a custom serializer, that will know how to serialize xml representations of the objects on the client-side, and deserialize on the server and vice versa.

I'll follow up in some post that describes how you can create different versions of your domain layer for use on either client-side or server-side.

The end result

Let's skip to the end result straight away. This is a little test that runs fine:

  0    Person p = new Person();
  1    p.Name = "Ruurd";
  2    p.MyProperty = 10;
  3    p.orders.Add("234");
  4    p.orders.Add("23asdf4");
  5    p.orders.Add("234345zs");
  6
  7
  8    IEditableBusinessObject editablePerson = p as IEditableBusinessObject;
  9
  10    editablePerson.CopyCurrentToLoaded();
  11
  12    editablePerson.BeginEdit();
  13
  14    p.Name = "Boeke";
  15    p.orders.Add("zxcvzxcvzxcvzxcv");
  16
  17    Assert.IsTrue(p.Name == "Boeke");
  18    Assert.IsTrue(p.orders.Count == 4);
  19
  20    editablePerson.CancelEdit();
  21
  22    Assert.IsTrue(p.orders.Count == 3);
  23    Assert.IsTrue(p.Name == "Ruurd");

Just so we are on the same page, we did not have to implement anything on the business object itself. Only use an attribute: the EditableBusinessObjectAttribute. It will take care of everything for ya.

  0 [EditableBusinessObject]
  1 [Serializable]
  2  public class Person
  3 {
  4   public int MyProperty { get; set; }
  5
  6   public string Name { get; set; }
  7
  8   public List<string> orders { get; set; }
  9
  10   public Person()
  11   {
  12    orders = new List<string>();
  13   }
  14
  15 }

Editable business objects

There is already a great usersample available on how to use PostSharp to implement this interface. I took a different route, but you should still check out the sample, because it is actually quite well put together.

My scenario has the following requirements:

  • implement IEditableObject (obviously)
  • Have a way to copy values to a 'Loaded' state: necessary to be able to send the 'original values' to Entity Framework
  • Retrieve that loaded state: will be used by the serializer, to actually create the original value serialization

So, I created the following interface that we will implement using PostSharp:

  0  public interface IEditableBusinessObject : IEditableObject
  1 {
  2   void RegisterFieldAccessAspect(FieldInterceptionAspect aspect);
  3
  4   void CopyCurrentToLoaded();
  5
  6   object RetrieveLoadedState(string FieldName);
  7
  8   bool HasPendingTransaction();
  9 }
  10

To implement, we use the familiar CompositionAspect.

For the real magic, we need to intercept all gets and sets of all fields in the business object.

Intercept field access

A very strong feature of PostSharp is the OnFieldAccessAspect. It allows you to actually intercept field access and route it to something different.
The implementation of IEditableBusinessObject knows when the businessobject is set to beginedit and should notify all fieldaspects. We do this by 'registering' the fieldaspect at the editableBusinessObject. This way, when our object is going to beginEdit mode, all we have to do is iterate our fieldaspects and let them know.

At that point the fieldaspect makes a copy of it's value to the corresponding statebag. If our value was not a value type, we make a deepcopy. I'm contemplating adding support for ICloneable, so we can possibly skip that step.

So, the begin, cancel and endedit methods on the fieldaspect look something like this:

  0   internal void BeginEdit()
  1   {
  2    if (needsBinaryCopy)
  3    {
  4     MemoryStream m = new MemoryStream();
  5     BinaryFormatter b = new BinaryFormatter();
  6     b.Serialize(m, CurrentState);
  7     m.Position = 0;
  8     PendingState = b.Deserialize(m);
  9    }
  10    else
  11    {
  12     PendingState = CurrentState;
  13    }
  14   } 
  15  
  16   internal void CancelEdit()
  17   {
  18    PendingState = null;
  19   }
  20
  21   internal void EndEdit()
  22   {
  23    CurrentState = PendingState;
  24    PendingState = null;
  25   }

And the get and set methods of the field look like this:

  0   public override void OnGetValue(FieldAccessEventArgs eventArgs)
  1   {
  2    IEditableBusinessObject editableObjectImpl = (IEditableBusinessObject)eventArgs.Instance;
  3    editableObjectImpl.RegisterFieldAccessAspect(this);
  4
  5    eventArgs.ExposedFieldValue = editableObjectImpl.HasPendingTransaction() ? PendingState : CurrentState;
  6   }
  7
  8   public override void OnSetValue(FieldAccessEventArgs eventArgs)
  9   {
  10    IEditableBusinessObject editableObjectImpl = (IEditableBusinessObject)eventArgs.Instance;
  11    editableObjectImpl.RegisterFieldAccessAspect(this);
  12
  13
  14
  15    if (editableObjectImpl.HasPendingTransaction())
  16    {
  17     PendingState = eventArgs.ExposedFieldValue;
  18    }
  19    else
  20    {
  21     CurrentState = eventArgs.ExposedFieldValue;
  22    }
  23   }

As you can see, it checks with the instance, whether we have a pending transaction (we have started beginedit). If we do, we write to the pendingstate object, instead of the current state.

I don't feel too comfortable with the code at this point, because I took quite a bit of shortcuts. So I'm not putting that online at this point. However, if you are really interested, let me know in the comments, and I'll clean it up.

Stay tuned, because the next step will be to get this to serialize nicely, with originalvalues and such.

Sunday, 16 March 2008 15:16:14 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback
 Friday, 14 March 2008

I just finished full support for using complex types in EFContrib. I thought I'd quickly share what complex types are and how they are used in Entity Framework.

Julie Lerman blogged about Complex Types here, where she also shows how to use them. Check her post for a great example.
In Daniel Simmons' words:
Complex types “Complex types” is the Entity Framework name for value properties which have more intricate structure than scalars. The canonical example is an Address type which contains several parts (street, city, state, etc.) Complex types are somewhat like entities except that they do not have any identity of their own (they are value types). This means that a complex type instance is always a part of some other enclosing entity—it can’t stand on its own, it doesn’t have relationships, etc. In this release, the mapping scenarios for complex types are significantly limited: inheritance is not supported, complex type properties cannot be null and they can only occur in single instances, not collections.

So, a complex type can be seen as a struct, without identity.
Let's create a complex type. I will have a person table with 3 address related columns. My person object though, should have a property named 'Address' which points to a class of type Address.
The CSDL looks like this:

        <EntityType Name="Person">
          <Key>
            <PropertyRef Name="PersonID" />
          </Key>
          <Property Name="PersonID" Type="Int32" Nullable="false" />
          <Property Name="FirstName" Type="String" Nullable="false" MaxLength="50" Unicode="false" />
          <Property Name="LastName" Type="String" Nullable="false" MaxLength="50" Unicode="false" />
          <Property Name="Address" Type="Self.Address" Nullable="false" />
        </EntityType>
        <ComplexType Name="Address">
          <Property Name="City" Type="String" Nullable="false" MaxLength="50" Unicode="false" />
          <Property Name="Street" Type="String" Nullable="false" MaxLength="50" Unicode="false" />
          <Property Name="PostalCode" Type="String" Nullable="false" MaxLength="10" Unicode="false" />
</ComplexType>

Pretty clear: our Person has an address property, with a type of 'Self.Address'. Make sure it is not Nullable. The Address is defined just like you would expect. Please know that the current designer does not allow designing complextypes visually, which is why I did it in xml.

The database looks like this:

        <EntityContainer Name="dbo">
          <EntitySet Name="Person" EntityType="ComplexTypesTestModel.Store.Person" />
        </EntityContainer>
        <EntityType Name="Person">
          <Key>
            <PropertyRef Name="PersonID" />
          </Key>
          <Property Name="PersonID" Type="int" Nullable="false"  StoreGeneratedPattern="Identity" />
          <Property Name="FirstName" Type="varchar" Nullable="false" MaxLength="50" />
          <Property Name="LastName" Type="varchar" Nullable="false" MaxLength="50" />
          <Property Name="Street" Type="varchar" Nullable="false" MaxLength="50" />
          <Property Name="City" Type="varchar" Nullable="false" MaxLength="50" />
          <Property Name="PostalCode" Type="varchar" Nullable="false" MaxLength="10" />
</EntityType>

Here we see a row with all columns in it. Darned DBA's!!

To map that database description to the classes, we take a look at the C-S mapping:

          <EntitySetMapping Name="Person">
            <EntityTypeMapping TypeName="IsTypeOf(EntityFrameworkContrib.PostSharp4EF.Testing.ComplexType.Person)">
              <MappingFragment StoreEntitySet="Person">
                <ScalarProperty Name="PersonID" ColumnName="PersonID" />
                <ScalarProperty Name="FirstName" ColumnName="FirstName" />
                <ScalarProperty Name="LastName" ColumnName="LastName" />
                <ComplexProperty Name="Address">
                  <ScalarProperty Name="City" ColumnName="City"/>
                  <ScalarProperty Name="Street" ColumnName="Street"/>
                  <ScalarProperty Name="PostalCode" ColumnName="PostalCode"/>
                </ComplexProperty>
              </MappingFragment>
            </EntityTypeMapping>
</EntitySetMapping>

As you can see, the complexproperty is defined within the Person mapping. That caught me off-guard for a while.

EFContrib support

I have not checked in the source yet, but I will shortly at http://www.codeplex.com/efcontrib.
As you know, my contribution project to Entity Framework aims to help you use Entity Framework without all the generated code. You can just create your own domain model and add one attribute. The system will actually change the code to facilitate the EDM during compilation. Leaving you with a clean model.

It was actually quite difficult to implement this behind the scenes. To support normal entitytypes, I have to implement the three IPoco interfaces. But complex types are radically different. In the end, I had to alter the code I put into the setters of your properties.
I also had to somehow get hold of a list of properties in your type that are complexTypes (in this case Address). When the system injects your entitytype with a changetracker, it should notify all complex types. I could have done that with reflection, but we all know that's really slow. So I actually generate a method in your entity: 'UpdateComplexTypes(tracker)' and insert that with the correct IL to set the tracker in all the complextype-properties. So the solution is as fast as it can get, completely on par with handwritten c#. I may have to write another post on how I did it.

Our domain objects look like this:

  0 [Poco("ComplexTypesTestEntities")]
  1  public class Person
  2 {
  3   public int PersonID { get; set; }
  4   public string FirstName { get; set; }
  5   public string LastName { get; set; }
  6   public Address Address { get; set; }
  7 }
  8
  9 [Poco("ComplexTypesTestEntities")]
  10  public class Address
  11 {
  12   public string City { get; set; }
  13   public string Street { get; set; }
  14   public string PostalCode { get; set; }
  15 }
  16

Now, this code will work great:

  0    using (ComplexTypesTestEntities context = new ComplexTypesTestEntities())
  1    {
  2     // clear out database
  3     foreach (Person old in context.Person)
  4     {
  5      context.DeleteObject(old);
  6     }
  7     context.SaveChanges();
  8
  9     Person p = new Person { FirstName = "Ruurd", LastName = "Boeke" };
  10
  11     // this will set the changetracker
  12     context.AddToPerson(p);
  13
  14     Address a = new Address { City = "Rotterdam", Street = "My Street", PostalCode = "1111 VA" };
  15     p.Address = a;
  16
  17     IGetChangeTracker ctA = PostSharp.Post.Cast<Address, IGetChangeTracker>(a);
  18     Debug.Assert(ctA.GetChangeTracker() != null);
  19
  20     Address b = new Address { City = "Seattle", Street = "redmond street", PostalCode = "2222 BB" };
  21     p.Address = b;
  22     Debug.Assert(ctA.GetChangeTracker() == null);
  23
  24     IGetChangeTracker ctB = PostSharp.Post.Cast<Address, IGetChangeTracker>(b);
  25     Debug.Assert(ctB.GetChangeTracker() != null);
  26
  27     context.SaveChanges();
  28    }

You can see me casting the object to the interface I implemented on lines 17 and 24.

Friday, 14 March 2008 17:36:55 (Romance Standard Time, UTC+01:00)  #    Comments [7]  |  Trackback
 Monday, 10 March 2008

I've been working on the PostSharp4EF project of EFContrib. I'm pleased to announce relationships are now supported.

This actually proved to be somewhat more work, because of all the things that are happening behind the scenes.
Entity Framework expects EdmRelationshipNavigationProperty attributes on top of the property that points to a relationship. But there is also the giant EdmRelationshipAttribute with about 8 constructor parameters.
So, I now generate these for you.

The next step was to actually get the relationship for you. I do that by removing the backing field, and replacing it with methods that access the relationshipmanager to get the relationship.

I do not want you to work directly with EF types, but you will need a way to Load relationships. So, I've introduced an interface with the appropriate Load and IsLoaded methods. Just in case you do want to hook into the EntityCollection and EntityReference, I've also supplied methods on that interface that will get you these types.

Let's look at a domain model:

  0 [Poco("SimpleRelationshipTestEntities")]
  1  public class Customer
  2 {
  3   public int CustomerID { get; set; }
  4   public string Name { get; set; }
  5
  6   public ICollection<Car> Cars { get; set; }
  7
  8   public ICollection<Order> Orders { get; set; }
  9 }
  10
  11 [Poco("SimpleRelationshipTestEntities")]
  12  public class Car
  13 {
  14   public int CarID { get; set; }
  15   public string Make { get; set; }
  16
  17   public Customer Customer { get; set; }
  18
  19 }
  20
  21 [Poco("SimpleRelationshipTestEntities")]
  22  public class Order
  23 {
  24   public int OrderID { get; set; }
  25   public int Amount { get; set; }
  26
  27   public Customer Customer { get; set; }
  28
  29
  30 }
  31

You might notice that I do not expose the concrete EF types, but instead expose ICollections.
After compilation, you can use this domainmodel like this:

  0    using (SimpleRelationshipTestEntities context = new SimpleRelationshipTestEntities())
  1    {
  2
  3     foreach (Car oldCar in context.Car)
  4     {
  5      IRelationshipLoader noLazyLoading = PostSharp.Post.Cast<Car, IRelationshipLoader>(oldCar);
  6
  7      bool wasLoaded = noLazyLoading.IsLoaded("Customer");
  8
  9      EntityReference<Customer> cu = noLazyLoading.GetRelatedReference<Customer>("Customer");
  10      cu.Load();
  11
  12      wasLoaded = noLazyLoading.IsLoaded("Customer");
  13     }
  14
  15
  16
  17     // clear out database
  18     foreach (Customer old in context.Customer)
  19     {
  20      IRelationshipLoader noLazyLoading = PostSharp.Post.Cast<Customer, IRelationshipLoader>(old);
  21
  22      bool wasLoaded = noLazyLoading.IsLoaded("Orders");
  23
  24      noLazyLoading.Load("Orders");
  25      wasLoaded = noLazyLoading.IsLoaded("Orders");
  26
  27      EntityCollection<Order> orders = noLazyLoading.GetRelatedCollection<Order>("Orders");
  28
  29      context.DeleteObject(old);
  30     }
  31     context.SaveChanges();
  32
  33
  34     Customer c = new Customer { Name = "Ruurd Boeke" };
  35     Customer c2 = new Customer { Name = "Test Customer" };
  36     Car car = new Car { Make = "Ferrari" };
  37     Order o1 = new Order { Amount = 10 };
  38     Order o2 = new Order { Amount = 20 };
  39     Order o3 = new Order { Amount = 30 };
  40
  41     car.Customer = c;
  42     car.Customer = c2// can re assign test
  43
  44     // add customer on order
  45     o1.Customer = c;
  46     o2.Customer = c;
  47     // add order on customer, new way
  48     c.Orders.Add(o3);
  49
  50
  51
  52     context.AddToCustomer(c);
  53     context.AddToCustomer(c2);
  54     context.SaveChanges();
  55    }
  56   }

Points of interest:
Line 5 casts your object to the implemented interface. This is checked at compile-time, so no worries about breaking at runtime. Using this cast, I can get to the EF types like I do at line 9 and line 27. Obviously, if you were inclined, you could place these methods on your domain classes. It does couple you to EF more though and clutters the code.

Next up are complex types. When that's done, I'm finished.

Quite pleased with this actually! ;-)

Monday, 10 March 2008 17:56:40 (Romance Standard Time, UTC+01:00)  #    Comments [5]  |  Trackback
 Thursday, 21 February 2008

This is the fourth of a series about how to go about using postcompilation in your solutions. You can read it as a tutorial on how to use PostSharp. I am very much new to that framework, but the power it provides could seriously change how you build your applications. While working on the EF contrib project, I had to dive into PostSharp, and I hope to share some of the things I learned along the way.

This post introduces the first real step I took: the compound aspect.

The full table of contents:

  • Introducing Entity Framework Contrib- Easy IPoco implementation V 0.1
  • Part II, Postsharp Core versus Postsharp Laos
  • Part III, the compound aspect
  • Part IV, the PocoInterfaceSubaspect (composition aspect)
  • Part V, hooking up the weaver
  • Part VI, the EdmScalarWeaver
  • Recap

    We wish to create an attribute that can be placed on top of our ordinary Poco class, that will magically transform it into a class that implements the 3 IPoco interfaces. These are needed by the Entity Framework to do it's work. We will use PostSharp to do this.
    Our previous post talked about the composite attribute and how it allows you to combine multiple actions into one attribute. That's easier to use for the endusers.

    This post we will look into the PocoInterfaceSubAspect and how it does it's job.

    The Composition aspect

    You can remember placing the PocoInterfaceSubAspect on the element like so:

                // implement the three IPOCO interfaces on the class
                collection.AddAspect(targetType, new PocoInterfacesSubAspect());

    Postsharp will instantiate our aspect during it's weaving. Our aspect inherits from CompositionAspect. Let's take a step back and discuss what the CompositionAspect does.

    The compositionAspect is an extremely powerful aspect which allows you to implement an interface onto another object. So let's say you want to make an object be an iList at runtime, without dealing with it in your source: use composition to implement iList!

    We are implementing the three iPoco interfaces. Because the CompositionAspect wants one type to composite (and I did not feel like doing it three times) I created a facade interface:

        public interface IPocoFacade : IEntityWithChangeTracker, IEntityWithKey, IEntityWithRelationships
        {
        }

    Now, how does the weaver go about using this aspect to actually implement the code needed? It will ask for the public interface to inject and then also ask for an implementation object. The implementation object is the one that gets to do the dirty work. PostSharp will basically inject that implementation object into your object and then create all your interface code to just use that implementation object.

    The PocoInterfacesSubAspect

    The complete aspect looks like this:

        [Serializable]
        sealed class PocoInterfacesSubAspect : CompositionAspect
        {

            public override object CreateImplementationObject(InstanceBoundLaosEventArgs eventArgs)
            {
                return new PocoImplementation(eventArgs.Instance);
            }

            public override Type GetPublicInterface(Type containerType)
            {
                return typeof(IPocoFacade);
            }

            /// <summary>
            /// Gets weaving options.
            /// </summary>
            /// <returns>Weaving options specifying that the implementation accessor interface (<see cref="IComposed{T}"/>)
            /// should be exposed, and that the implementation of interfaces should be silently ignored if they are
            /// already implemented in the parent types.</returns>
            public override CompositionAspectOptions GetOptions()
            {
                return
                    CompositionAspectOptions.GenerateImplementationAccessor |
                    CompositionAspectOptions.IgnoreIfAlreadyImplemented;
            }
        }

     

    Clearly, we are more interested in the implementation object.

    The implementation

    Part of the implemenation object looks like this:

       class PocoImplementation : IPocoFacade
        {
            private readonly object instance;

            public PocoImplementation(object instance)
            {
                this.instance = instance;
            }
    }

    You can see it implements the IPocoFacade interface. It expects our businessobject that was decorated with the Poco attribute in it's constructor.

    We now just look at the code the Ado.Net team has given us to see how to implement these interfaces.

    The IEntityWithKey for instance, is quite easy:

            #region key
            EntityKey _entityKey = null;

            // Define the EntityKey property for the class.
            EntityKey IEntityWithKey.EntityKey
            {
                get
                {
                    return _entityKey;
                }
                set
                {
                    // Set the EntityKey property, if it is not set.
                    // Report the change if the change tracker exists.
                    if (_changeTracker != null)
                    {
                        _changeTracker.EntityMemberChanging("-EntityKey-");
                        _entityKey = value;
                        _changeTracker.EntityMemberChanged("-EntityKey-");
                    }
                    else
                    {
                        _entityKey = value;
                    }
                }
            }
            #endregion

    Done.

    Since I first want to know if there is interest, I have not implemented relationships and complex types yet.

    Thursday, 21 February 2008 12:25:32 (Romance Standard Time, UTC+01:00)  #    Comments [5]  |  Trackback
     Monday, 18 February 2008

    In this post I'd like to introduce version 0.1 of the first Entity Framework contribution project: Automatically implement the IPoco interfaces.
    The project is aimed at helping you build your domain layer in a more persistence ignorant way, than is possible at this moment.

    [official codeplex location of the project is here]

    The full table of contents:

    The Problem: baseclass needed

    Microsoft is on the brink of releasing the Entity Framework. It is at beta 3 at this moment. If you are reading this blog, you are probably familiar with it, but let's do a quick summary:
    The Entity Framework is a framework that maps between a database and your domain objects. It's grand vision is to easily allow you to (with a funky design-experience) create (multiple) conceptual models that know how to talk to the database. Although more than an OR-mapper, most people like to position it as such anyway.
    EF is an abstraction layer on top of your datastore and will allow you to work with business objects that actually make sense from an object-oriented perspective, instead of making you work with datarows, tables and sets.

    One part of the criticism that the Entity Framework gets at this moment, is the lack of persistence ignorance. This means that, when you use the Entity Framework, you will have to create business entities that are aware of the Entity Framework (they need to derive from a Entity Framework baseclass).
    This goes against too many principles to mention, and the ADO.Net team have gotten quite a bit of comments about it (other more mature frameworks, like nHibernate do not force you into this). Rightfully so!
    In the end, Daniel Simmons blogged about the criticism here: Persistence Ignorance: OK, I think I get it now.

    The suggested Solution: implement interfaces

    In order to take away the need to implement a base-class, the EF-team created a few interfaces that need to be implemented. That is as far as they can go in the first release.

    So, you can implement 3 interfaces on your business objects, and no baseclass is needed. 
    Although much better, I feel I should not have to spend time on, or burden my domain layer with, code to facilitate data access. My domain layer should be able to focus on one thing: solving the business problems of the client.
    By introducing other code to my domain layer, developers will be distracted.

    Bill McCafferty posts about DDD (Domain Driven Design) and EF here. He concludes:

    In short, and at the risk of being laconic, I feel that the ADO.NET Entity Framework does for data communications what the ASP.NET page life cycle did for the presentation layer.  In trying to introduce simplification and increased productivity, it's actually going to result in higher complexity and decreased maintainability in the long run.  I appreciate what Microsoft is trying to do, and absolutely love some of their other ideas, but, for now, I'm going to pass on the ADO.NET Entity Framework.

    Billy McCafferty

    He is quite right!!

    EF-Contrib: Easing the implementation of these interfaces

    The 3 interfaces we are talking about are:

    • IEntityWithChangeTracker
    • IEntityWithKey
    • IEntityWithRelationships

    Implementing these interfaces is sometimes called "IPoco": Poco stands for Plain Old C# (or Code) Object, and the I in IPoco means that you can still use your Poco object but have to implement these interfaces. (so, not Poco at all... but still!)

    The current checked in project (find it here) uses Postsharp to actually change the IL-code of your assembly and implements these interfaces. That means that you can build a domain layer with a class like this:

        [Poco("ConnectionName")]
        public class Person
        {
            public int PersonID { get; set; }
            public string Firstname { get; set; }
            public string Lastname { get; set; }
        }

    After compilation, the class will actually look a bit different on disk:

        public class Person : IEntityWithChangeTracker, IEntityWithKey, IEntityWithRelationships
        {
    ...
        }

    So you can use this Person class, like you would use the classes that EF generates.

    It is important to understand that there will be very little runtime performance costs involved. The code transformation is done at compile-time, once. At runtime, there is no magic AOP or whatever involved.

    This approach is used by several other OR-Mappers and is very common in the Java world.

    Is this Persistence Ignorance?

    Obviously, it's not. Hopefully, in version 2.0 of the Entity Framework, full ignorance is achieved. However, if you want to use EF at your datalayer today, this approach will let you focus on the important stuff, instead of data access code.

    Imagine changing your conceptual model. When implementing IPoco yourself, you will have to take care to change all kinds of attributes on top of your properties. This will quickly become a burden.

    How does it work?
    • You will need to download and install Postsharp on all the machines that will build your application (developer machines and teambuild machine(s)).
    • Your domain layer will have to reference the EntityFrameworkContrib.PostSharp4EF assembly, and the PostSharp.Laos and PostSharp.Public assemblies. By referencing these, Postsharp will know to do a post-compilation phase on your assemblies.
    • You will need to supply a 'psproj' file in your assembly, to let our attribute know where it should look to actually do the implementation. This allows me to seperate the implementation assembly from what you need at runtime!
    • You have already created your edmx file, which EF will dissect into the individual .csdl, .msl and .ssdl files and place them in your bin/debug folder.
    • The project for now assumes a connection string to be present in your app.config
    • You can create your own simple business object.
    • That connection string is needed during the postcompilation phase to get to the individual mapping files, so use the attribute [Poco("")] to let us know you need to change this class.
    • The interfaces are implemented and the setters of your properties are modified to actually do changetracking
    • Actually, at this moment: INotifyPropertyChanged is implemented as well (let me know if you actually want this).

    So, let's first look at the psproj file you need. In the Test-project, there is one already:

    <Project xmlns="http://schemas.postsharp.org/1.0/configuration">
    	<SearchPath Directory="../EntityFrameworkContrib.PostSharp4EF.Weaver/bin/{$Configuration}"/>
    	<SearchPath Directory="{$SearchPath}" />
    	<Tasks>
    		<AutoDetect />
    		<Compile TargetFile="{$Output}" IntermediateDirectory="{$IntermediateDirectory}"  CleanIntermediate="false" />
    	</Tasks>
    </Project>

    The referenced assembly EntityFrameworkContrib.PostSharp4EF only defines the Poco attribute, but does not contain the actually 'code-weaving'. If we would have placed the code-weaving in the same assembly as the Poco-attribute, you would have a much larger assembly to reference and you could get into licensing problems. By separating them, you only need to reference a tiny assembly.

    The weaving assembly should not be distributed with your final product!

    However, during the build, PostSharp does need to find the weaving assembly. Therefor, you need to create a psproj file that extends it's normal searchpath to also include the weaving dll.
    Take care in naming the file: it should be named "projectname.psproj".

    When the project is more mature, you might find it best to actually just place the weaving assembly into one of the default searchpaths for postsharp to find, and you will not need this psproj file.

    Now, let's look at our attribute:
    In it's constructor, it takes the name of the EDMcontainer, which should match your connection string. I have also added a few properties: Name, NamespaceName, PathToConfigFile. I'll get back to these in a later post. In the future, others will be added.

    During the weaving, I have to do quite a bit of work to actually get to the correct mapping files. So, I try to load in your app.config and extract the file path's from it. The Testproject has the following app.config:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <connectionStrings>
        <add name="OneSimpleTypeConnection" connectionString="metadata=.\bin\debug\OneSimpleType\OneSimpleType.csdl|.\bin\debug\OneSimpleType\OneSimpleType.ssdl|.\bin\debug\OneSimpleType\OneSimpleType.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=VISTAX64\SQLEXPRESS;Initial Catalog=EntityFrameworkTest;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />
      </connectionStrings>
    </configuration>

    So, after loading that app.config, I use the supplied ConnectionContainer to get that connectionstring, and then use some simple regex work to get the path's to the mapping files. Then I try to load these to create a MetadataWorkspace.

    When I finally have a MetadataWorkspace, stuff get's easier: I can iterate the properties in our original class and find the property in the metadataworkspace. Then I create the correct EDMScalar Attributes on top of those.

    Implementing the interfaces is done by PostSharp, where it will look at an interface and just use a class I provide to call when one of the interface methods is called.

    The result

    Let's look through reflector at how the end result looks like. I won't show the methods, to keep things short and sweet.

      1 [EdmEntityType(Name="Person", NamespaceName="EntityFrameworkContrib.PostSharp4EF.Tests.OneSimpleType")]
      2 public class Person : INotifyPropertyChanged, IComposed<INotifyPropertyChanged>, IProtectedInterface<IFirePropertyChanged>, IPocoFacade, IComposed<IPocoFacade>
      3 {
      4     // Fields
      5     private IPocoFacade ~EntityFrameworkContrib.PostSharp4EF.IPocoFacade;
      6     private readonly InstanceCredentials ~instanceCredentials;
      7     private INotifyPropertyChanged ~System.ComponentModel.INotifyPropertyChanged;
      8     [CompilerGenerated]
      9     private string <Firstname>k__BackingField;
    10     [CompilerGenerated]
    11     private string <Lastname>k__BackingField;
    12     [CompilerGenerated]
    13     private int <PersonID>k__BackingField;
    14
    15     // Methods
    16     static Person();
    17     public Person();
    18     void INotifyPropertyChanged.add_PropertyChanged(PropertyChangedEventHandler value);
    19     EntityKey IEntityWithKey.get_EntityKey();
    20     RelationshipManager IEntityWithRelationships.get_RelationshipManager();
    21     void INotifyPropertyChanged.remove_PropertyChanged(PropertyChangedEventHandler value);
    22     void IEntityWithKey.set_EntityKey(EntityKey value);
    23     void IEntityWithChangeTracker.SetChangeTracker(IEntityChangeTracker changeTracker);
    24     protected InstanceCredentials GetInstanceCredentials();
    25     [DebuggerNonUserCode]
    26     IPocoFacade IComposed<IPocoFacade>.GetImplementation(InstanceCredentials credentials);
    27     [DebuggerNonUserCode]
    28     INotifyPropertyChanged IComposed<INotifyPropertyChanged>.GetImplementation(InstanceCredentials credentials);
    29     [DebuggerNonUserCode]
    30     IFirePropertyChanged IProtectedInterface<IFirePropertyChanged>.GetInterface(InstanceCredentials credentials);
    31
    32     // Properties
    33     [EdmScalarProperty(IsNullable=true)]
    34     public string Firstname { [CompilerGenerated] get; [CompilerGenerated] set; }
    35     [EdmScalarProperty(IsNullable=false)]
    36     public string Lastname { [CompilerGenerated] get; [CompilerGenerated] set; }
    37     [EdmScalarProperty(IsNullable=false, EntityKeyProperty=true)]
    38     public int PersonID { [CompilerGenerated] get; [CompilerGenerated] set; }
    39 }
    40
    41

    Line 1 implements the needed EntityType attribute for EDM to work.
    Line 2 shows that INotifyPropertyChanged and IPocoFacade is implemented. The facade interface just hides the 3 IPoco interfaces, so that's them! PostSharps adds IComposed interfaces as well.
    Line 26 shows a call to the GetImplementation method of that interface. This way, a class I have added is returned where the actual work of the interface is done.
    Line 33, 35 and 38 show the EDMScalarProperties being set.

    What it does not do at this moment

    I do not set default values for fields and I haven't spend any time on complex types and relations.

    I first want to gauge community interest before spending more time on this project. So let me know if you would use this approach if it would be complete. I'm quite sure these things aren't too hard to accomplish, but they will take some time.

    The Future

    I'd like the EntityFramework Contrib project to provide easy tools to use EF in an enterprise system. I'm mostly interested in client/server SOA solutions. Other projects that might help in that aspect:

    • A custom changetracker that can be used on the client. This way the client will not have to reference Entity Framework at all.
    • Better serialization possibilities. Note that I do not automatically place datacontract attributes on top of the properties. I think it was a mistake for the ADO.Net team to implement their codegen to do this. (although I understand why).
      When I serialize a EF entity at this moment, I see all kinds of references to EF in the xml. I do not like that, and would like a beautiful clean xml representation of my business objects. (I don't want to be forced to use DTO's.).
    • Serializing original values. I can see a representation of the value with a xml attribute that shows what the original value was.

     

    Feel free to contact me, or leave a comment here or at the projects home to let me know if you are interested!

    kick it on DotNetKicks.com

    Monday, 18 February 2008 14:50:21 (Romance Standard Time, UTC+01:00)  #    Comments [46]  |  Trackback
     Saturday, 05 January 2008

    Let's mix things up!
    One of the strengths of the Entity Framework is it's mapping mechanism, which uses views to represent the data needed for an entity. As they call it 'some clever magic' allows the EF to fold and unfold data into views, solving the problem that most database systems (including oracle) do not solve for you: updating and inserting into a view that consists of more than 2 tables.
    This allows us to map more information when needed.

    In our previous examples, an employee table was defined in the database and our conceptual model used the Table Per Hierarchy mapping strategy to map developers, testers and business analists to that table. We now find that we have quite a bit of information that we need to store about the developers (such as their skill-set) that is of no use to the other types of employees. We could very well add a bunch of nullable columns to the employee table. However, one can only sustain that much filth for a certain time period ;-) Going down that path will soon get out of hand. It's better to create a new table that will hold the information we seek. (Or would you rather create a universal table???)

    Thus a new table 'DevelopmentSkills' is added and a primary key DeveloperID is created, along with a few boolean columns. A foreign key relation is created between the Employee table and the new table. Nothing fancy:

    EF_Combining_DBDiagram.jpg

    I've learned by now that it's best to create the SSDL by hand. So I add the new table to the SSDL:

            <EntityType Name="DevelopmentSkills">
              <Key>
                <PropertyRef Name="DeveloperID" />
              </Key>
              <Property Name="DeveloperID" Type="int" Nullable="false" />
              <Property Name="WPF" Type="bit" Nullable="false" Default="false" />
              <Property Name="WCF" Type="bit" Nullable="false" Default="false" />
              <Property Name="WF" Type="bit" Nullable="false" Default="false" />
              <Property Name="EF" Type="bit" Nullable="false" Default="false" />
            </EntityType>
    And the more important association:
            <Association Name="FK_DevelopmentSkills_Employee">
              <End Role="Employee" Type="EntityFrameworkTestModel1.Store.Employee" Multiplicity="1" />
              <End Role="DevelopmentSkills" Type="EntityFrameworkTestModel1.Store.DevelopmentSkills" Multiplicity="0..1" />
              <ReferentialConstraint>
                <Principal Role="Employee">
                  <PropertyRef Name="EmployeeID" />
                </Principal>
                <Dependent Role="DevelopmentSkills">
                  <PropertyRef Name="DeveloperID" />
                </Dependent>
              </ReferentialConstraint>
            </Association>

    This association represents the foreignkey in the database and should be pretty clear by now.
    Don't forget to define the sets in the entitycontainer.

    Then I was able to use the designer to first create extra properties in the 'einstein' class, our junior developer ;-)
    In the mapping designer, choose to map to DevelopmentSkills. Set the DeveloperID column to the PersonID property and map the remaining properties.

    Pretty neat, we did not have to map another class, but instead, just extended our current class.

    That means that this code is now possible:

    Einstein smartNerd = new Einstein()
    {
    Firstname = "Albert",
    Lastname = "Einstein",
    Language = "C# 3.5",
    WCF = true, WPF = true, WF = true, EF = true,
    TeamLeader = e,
    };
    context.AddToPerson(smartNerd);

    Elvis elvis = new Elvis()
    {
    Firstname = "Elvis",
    Lastname = "Presley",
    Language = "C# 2.0",
    WPF = true, EF = true,
    TeamLeader = e,
    };
    context.AddToPerson(elvis);

    One thing to note though: the current designer makes a mistake when mapping the extra table to the Einstein class. It keeps adding new entitytypemappings in the CSDL, with the new mapping fragment (to developmentskills table) instead of combining the fragments in the already defined entitytypemapping. This leads to an error keeping the designer from showing any info. I had to hand edit a few times ;-(

     

     

    Saturday, 05 January 2008 23:15:36 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback

    We have seen two types of inheritance modeling, at this point I'm interested in modeling an association. This actually turned out to be harder then I had expected, even though the documentation on this subject is good and plentyfull ;-)

    However, since you are still reading, I will create a very simple example in the employee class, such that an employee needs to report to another employee.
    Remember that employee inherits from person. I was happy to see that I was indeed able to create the relationship!

    I've added a new column in the employee table, named: ReportsToID and a foreignkey relation that specifies the primary key base to be Employee/EmployeeID and the foreign key base to be Employee/ReportsToID. In database lingo this simple means that ReportsToID can be filled with an exact EmployeeID and that this relationship is verified (for instance, when deleting an employee, but still having other employees which report to the deleted employee).

     Let's look at the SSDL that I created to match this new foreignkey relationship:

    In the EntityContainer section:
              <AssociationSet Name="FK_Employee_Manager"
                              Association="EntityFrameworkTestModel1.Store.FK_Employee_Manager">
                <End Role="Manager" EntitySet="Employee" />
                <End Role="Members" EntitySet="Employee" />
              </AssociationSet>
    And the mentioned AssociationSet:
            <Association Name="FK_Employee_Manager">
              <End Role="Manager" Type="EntityFrameworkTestModel1.Store.Employee" Multiplicity="0..1" />
              <End Role="Members" Type="EntityFrameworkTestModel1.Store.Employee" Multiplicity="*" />
              <ReferentialConstraint>
                <Principal Role="Manager">
                  <PropertyRef Name="EmployeeID" />
                </Principal>
                <Dependent Role="Members">
                  <PropertyRef Name="ReportsToID" />
                </Dependent>
              </ReferentialConstraint>
            </Association>

    As you can see, I named the roles: Manager and Members.
    The association can be interpreted as follows: An employee (a Member) can have zero or one Manager. A Manager can have zero to infinite Members.

    Let's take a look at the C-side of life.
    In the EntityContainerSection:
              <AssociationSet Name="TeamMemberToTeamLeader"
                              Association="EntityFrameworkTestModel1.TeamMemberToTeamLeader">
                <End Role="TeamMembers" EntitySet="Person" />
                <End Role="TeamLeader" EntitySet="Person" />
              </AssociationSet>
    And the Association is defined as:
            <Association Name="TeamMemberToTeamLeader">
              <End Type="EntityFrameworkTestModel1.Employee" Role="TeamLeader" Multiplicity="0..1" />
              <End Type="EntityFrameworkTestModel1.Employee" Role="TeamMembers" Multiplicity="*" />
            </Association>

    I like to use real desciptive names, but this should be easy enough to follow.

    Also, I added navigationProperties to my model, so I can easily follow an association:
            <EntityType Name="Employee" BaseType="EntityFrameworkTestModel1.Person">
              <NavigationProperty Name="TeamLeader" Relationship="EntityFrameworkTestModel1.TeamMemberToTeamLeader" FromRole="TeamMembers" ToRole="TeamLeader" />
              <NavigationProperty Name="TeamMembers" Relationship="EntityFrameworkTestModel1.TeamMemberToTeamLeader" FromRole="TeamLeader" ToRole="TeamMembers" />
            </EntityType>

    Remember that an association is an independent entity, it only defines a relation that can be traversed. We need Navigationproperties to actually use the association. This way it can be shared between models.

    The actual mapping between the store and the conceptual model is interesting:
              <AssociationSetMapping Name="TeamMemberToTeamLeader"
                                     TypeName="EntityFrameworkTestModel1.TeamMemberToTeamLeader"
                                     StoreEntitySet="Employee" >
                <EndProperty Name="TeamMembers">
                  <ScalarProperty Name="PersonID" ColumnName="EmployeeID" />
                </EndProperty>
                <EndProperty Name="TeamLeader">
                  <ScalarProperty Name="PersonID" ColumnName="ReportsToID" />
                </EndProperty>
                <Condition ColumnName="ReportsToID" IsNull="false" />
              </AssociationSetMapping>

    Here you can see that I am mapping the ScalarProperty PersonID instead of EmployeeID; remember we are using inheritance here.

    The condition is needed to solve some errors I was having. I think it can be read as: the association only works if there is a reportsID value set.

    Some test code:

    Employee e = new Employee();
    e.Firstname = "Ian";
    e.Lastname = "Mort";
    context.AddToPerson(e);

    Einstein smartNerd = new Einstein();
    smartNerd.Firstname = "Albert";
    smartNerd.Lastname = "Einstein";
    smartNerd.Language = "C# 3.5";
    smartNerd.TeamLeader = e;
    context.AddToPerson(smartNerd);

    Elvis elvis = new Elvis();
    elvis.Firstname = "Elvis";
    elvis.Lastname = "Presley";
    elvis.Language = "C# 2.0";
    elvis.TeamLeader = e;
    context.AddToPerson(elvis);

    At this point I can check that e.TeamMembers has a count of 2 and both employees have a teammember property! So, everything working as expected.

    Reading back this post, I can see it was actually pretty simple. However, the syntax seems to be overly complex and a small mistake leads to weird errors!

     

    Saturday, 05 January 2008 15:09:31 (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  Trackback
     Friday, 04 January 2008

    Last post showed a very simple database setup with a Person, a Customer and an Employee-table. They were mapped to different classes in what is called a Table per Type mapping.

    A different kind of mapping strategy is the Table Per Hierarchy mapping, where all the types in your hierarchy are mapped to the same table. In many cases your dba will not understand why there should be different tables for information that can clearly be represented within the same table! For instance, different types of employees (developer, manager, architects) will certainly re-use the employee table, where very often a column is added to differentiate between these types.

    Far be it from me to disagree with such a database-schema. It makes perfect sense and is a clear example of the Object relational impedance mismatch. The domain-model needs to break free of these kinds of reasoning and needs to define it's own hierarchy.
    It can do so by leveraging the column that was added to diffentiate between types. In OR-Mapping, it is called a discriminator column, as the system can use it to discriminate between different the class-type it should use.

    I added a number of fun classes to the model, that represent developers: Einstein, Elvis and Mort. In this company, each inherits properties from the other, in a possibly unexpected way ;-)
    There is also the Business analist and a Tester.

    All these types have properties that are mapped to the same table. However, as your dba has come to understand, the different types of employees do differ a little and in time this has led to the introduction of a few extra columns in the employee table: 'ProgrammingLanguage' and 'TestMethodology'. Too bad these have to be nullable, because they don't make sense in all cases!
    Also, the functionname column of the previous post was changed to functiontype (int) and will act as the discriminator.

    Our database now looks like this:

    EF_TPH_DBDiagram..jpg

    Nothing fancy here.

    To create the conceptual model, I could use the designer. Again, if I update from the database, the model becomes useless, but editing the SSDL was easy enough in this case.
    Adding the new entities in the model designer was also easy:

    • There should not be a scalar property 'FunctionType' in the model. The discriminator works behind the scenes, and that is a good thing! As a user of the domain model, you should not need to know about it.
    • Only when you delete that property, can it be used as a 'condition', which basically is the condition that EF uses to see which class-type it should instantiate.
    • To map the condition, you need to map the various types to the employee table, even though they are already mapped through their parent 'Employee'!! No properties need to be mapped though.
    • When adding the condition, a value can be set. When you set the value, the designer does make an error in the xml which you will have to fix yourself!! So, when I wanted the type 'Einstein' to have the condition 'FunctionType = 1', I let the designer create it, and went to the line the build error indicates as being wrong. There I changed some weird value like '_x3301' to just '1'.

    The model now looks like this:

    EF_TPH_ConceptualModel..jpg

    Using the following test code:

    ....

    Einstein smartNerd = new Einstein();
    smartNerd.Firstname = "Albert";
    smartNerd.Lastname = "Einstein";
    smartNerd.Language = "C# 3.5";
    context.AddToPerson(smartNerd);

    Elvis elvis = new Elvis();
    elvis.Firstname = "Elvis";
    elvis.Lastname = "Presley";
    elvis.Language = "C# 2.0";
    context.AddToPerson(elvis);

    Mort mort = new Mort();
    mort.Firstname = "Mort";
    mort.Lastname = "Builder";
    mort.Language = "VB.Net";
    context.AddToPerson(mort);

    BusinessAnalist George = new BusinessAnalist();
    George.Firstname = "George";
    George.Lastname = "Clooney";
    context.AddToPerson(George);

    Tester tester = new Tester();
    tester.Firstname = "UnitTests";
    tester.Lastname = "Rock";
    tester.Methodology = "TMap";
    context.AddToPerson(tester);

    ....

    I got the following expected outcome:

    Ian, Mort is a Employee
    Albert, Einstein is a Einstein
    Ruurd, Boeke is a Person
    Silvia, Banana is a Customer
    George, Clooney is a BusinessAnalist
    UnitTests, Rock is a Tester
    Elvis, Presley is a Elvis
    Mort, Builder is a Mort

    The employee table was filled like this:

    55 0 NULL NULL
    56 1 C# 3.5 NULL
    59 4 NULL NULL
    60 5 NULL TMap
    61 2 C# 2.0 NULL
    62 3 VB.Net NULL

    So, that's all there is to it.
    Hopefully the data-team will fix the mapping bug in the next ctp!

    Next up, I will mix it up just a bit.

    Friday, 04 January 2008 01:17:45 (Romance Standard Time, UTC+01:00)  #    Comments [7]  |  Trackback
     Wednesday, 02 January 2008

    I'm going to jump right into the Entity Framework here, with a simple how-to. If you want a gentle introduction into this technology, you can probably read some future posts, but you will be far better off reading the ADO.Net teamblog or better still, read all of the entries of Danny Simmons.

    An OR-mapper needs to be flexible in mapping your domain classes, so you can describe your domain as truthfully as possible. The entity framework positions itself to be more than an OR-Mapper: it sees itself as a translation technology between models. One of those models is defined by your database, the other by your domain (your conceptual model). It's interesting to see what types of inheritance are possible. In this post I will give a sample of the Table Per Type (TPT) inheritance, where you define an inheritance in your conceptual model and use different tables to persist the data.

    The way to implement this is fairly straightforward and documented, however, I certainly had some problems getting it to work. As did Scott Allen, so I thought I would create a small walk through for this scenario.

    EF_TBT_DBDiagram.jpg

    As you can see, my database (SqlExpress) has 3 tables. The 'Person' table, a customer table and an employee table. There are foreign key relations between them, with the Person table being the Primary/Unique Key Base Table and the Customer and Employee tables being the Foreign Key Base Tables. It is important to note that the PersonID column is set up to automatically generate ID's, and the CustomerID and EmployeeID columns are not: we want to create a situation where an object like Customer is persisted to these two tables (customer and person) and the Person table is the one supplying a new ID. The Customer table will just use that PersonID as it's own CustomerID.

    That concludes the database schema, next up is the conceptual model, ugh, I mean domain model:

    EF_TBT_ConceptualModel.jpg

    This is how I want to my conceptual model to look like.  

    When you have just generated the model from the database, the foreign key relations are visible. Remove them! Then, also remove the CustomerID and EmployeeID properties that were generated. Add the two inheritance links.
    Since Customer already maps to Person (through the inheritance) you do not have to map these again. You do have to add a mapping to the customer table. The key point here is that the CustomerID column needs to be mapped to the PersonID property. Same goes for Employee.

    Now, this is all there is to it. Before we dive into the XML generated, let me just point this out: when you update from the database again, the designer will fail. This is a major problem, where the synchronization just isn't good enough. It will encounter problems with the foreign key associations that it has recreated. I hope this gets fixed in the following CTP.

    Now, although deceptively easy through the designer, I have a gut-feeling that it's going to be best to actually understand all the XML mapping that is generated. Just like the WPF and WF designers immediately made me turn to learning Xaml and Xoml, I feel that this designer is going to force me to learn CSDL and CS mapping pretty quickly.

    When opening the edmx file with the XML editor, quickly use ctrl-E-F to format everything. The designer creates very long lines.
    The SSDL content is unimportant, since it represents the database and should not be tinkered with here.
    The CSDL is as follows:

        <edmx:ConceptualModels>
          <Schema Namespace="EntityFrameworkTestModel1" Alias="Self" xmlns="http://schemas.microsoft.com/ado/2006/04/edm">
            <EntityContainer Name="EntityFrameworkTestEntities4">
              <EntitySet Name="Person" EntityType="EntityFrameworkTestModel1.Person" />
            </EntityContainer>
            <EntityType Name="Customer" BaseType="EntityFrameworkTestModel1.Person">
              <Property Name="CustomerDiscount" Type="Int32" Nullable="false" />
            </EntityType>
            <EntityType Name="Employee" BaseType="EntityFrameworkTestModel1.Person">
              <Property Name="FunctionName" Type="String" Nullable="false" MaxLength="50" />
            </EntityType>
            <EntityType Name="Person">
              <Key>
                <PropertyRef Name="PersonID" />
              </Key>
              <Property Name="PersonID" Type="Int32" Nullable="false" />
              <Property Name="Firstname" Type="String" Nullable="false" MaxLength="50" />
              <Property Name="Lastname" Type="String" Nullable="false" MaxLength="50" />
            </EntityType>
          </Schema>
        </edmx:ConceptualModels>

    Note a container with only one set: the Person set. Then the three types are defined. Only the Person type has a key identified, the Customer and the Employee do not!

    The C-S mapping then, glues this model to the SSDL:

          <Mapping Space="C-S" xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
            <EntityContainerMapping StorageEntityContainer="dbo" CdmEntityContainer="EntityFrameworkTestEntities4">
              <EntitySetMapping Name="Person">
                <EntityTypeMapping TypeName="IsTypeOf(EntityFrameworkTestModel1.Person)">
                  <MappingFragment StoreEntitySet="Person">
                    <ScalarProperty Name="PersonID" ColumnName="PersonID" />
                    <ScalarProperty Name="Firstname" ColumnName="Firstname" />
                    <ScalarProperty Name="Lastname" ColumnName="Lastname" />
                  </MappingFragment>
                </EntityTypeMapping>
                <EntityTypeMapping TypeName="IsTypeOf(EntityFrameworkTestModel1.Customer)">
                  <MappingFragment StoreEntitySet="Customer">
                    <ScalarProperty Name="PersonID" ColumnName="CustomerID" />
                    <ScalarProperty Name="CustomerDiscount" ColumnName="CustomerDiscount" />
                  </MappingFragment>
                </EntityTypeMapping>
                <EntityTypeMapping TypeName="IsTypeOf(EntityFrameworkTestModel1.Employee)">
                  <MappingFragment StoreEntitySet="Employee">
                    <ScalarProperty Name="PersonID" ColumnName="EmployeeID" />
                    <ScalarProperty Name="FunctionName" ColumnName="FunctionName" />
                  </MappingFragment>
                </EntityTypeMapping>
              </EntitySetMapping>
            </EntityContainerMapping>
          </Mapping>

    Here we see the PersonID being mapped to either the CustomerID column or the EmployeeID column. Interesting!

    In code, this allows us to do the following:

    EntityFrameworkTestEntities4 context = new EntityFrameworkTestEntities4();


    // inserting some
    Person p = new Person();
    p.Firstname = "Ruurd";
    p.Lastname = "Boeke";
    context.AddToPerson(p);

    Customer c = new Customer();
    c.Firstname = "Silvia";
    c.Lastname = "Banana";
    c.CustomerDiscount = 10;
    context.AddToPerson(c);

    Employee e = new Employee();
    e.Firstname = "Ian";
    e.Lastname = "Mort";
    e.FunctionName = "Developer";
    context.AddToPerson(e);

    context.SaveChanges();

    IQueryable<Person> persons =
    from person in context.Person
    select person;

    foreach (Person person in persons)
    {
    Console.WriteLine("{0}, {1} is a {2}",
    person.Firstname, person.Lastname, person.GetType().Name);
    }

    Console.ReadLine();

    Did you notice that the context was first saved, before the Linq query was executed? It's easy to forget, but the query is executed on the database, not on a Union of objects in the database and in the context.

    The output is as expected:

    Ruurd, Boeke is a Person
    Silvia, Banana is a Customer
    Ian, Mort is a Employee

    What I really like about this mapping strategy, is the fact that no discriminator column was needed. The system knows that an employee is an employee because of the existence of the record in the employee table. Let's quickly look at the generated query

    SELECT
    CASE WHEN (( NOT (([UnionAll1].[C2] = 1) AND ([UnionAll1].[C2] IS NOT NULL))) AND ( NOT (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL)))) THEN '0X' WHEN (([UnionAll1].[C2] = 1) AND ([UnionAll1].[C2] IS NOT NULL)) THEN '0X0X' ELSE '0X1X' END AS [C1],
    [Extent1].[PersonID] AS [PersonID],
    [Extent1].[Firstname] AS [Firstname],
    [Extent1].[Lastname] AS [Lastname],
    CASE WHEN (( NOT (([UnionAll1].[C2] = 1) AND ([UnionAll1].[C2] IS NOT NULL))) AND ( NOT (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL)))) THEN CAST(NULL AS int) WHEN (([UnionAll1].[C2] = 1) AND ([UnionAll1].[C2] IS NOT NULL)) THEN [UnionAll1].[CustomerDiscount] END AS [C2],
    CASE WHEN (( NOT (([UnionAll1].[C2] = 1) AND ([UnionAll1].[C2] IS NOT NULL))) AND ( NOT (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL)))) THEN CAST(NULL AS nvarchar(50)) WHEN (([UnionAll1].[C2] = 1) AND ([UnionAll1].[C2] IS NOT NULL)) THEN CAST(NULL AS nvarchar(50)) ELSE CAST( [UnionAll1].[C1] AS nvarchar(50)) END AS [C3]
    FROM [dbo].[Person] AS [Extent1]
    LEFT OUTER JOIN (SELECT
        [Extent2].[CustomerID] AS [CustomerID],
        [Extent2].[CustomerDiscount] AS [CustomerDiscount],
        CAST(NULL AS nvarchar(max)) AS [C1],
        cast(1 as bit) AS [C2],
        cast(0 as bit) AS [C3]
        FROM [dbo].[Customer] AS [Extent2]
    UNION ALL
        SELECT
        [Extent3].[EmployeeID] AS [EmployeeID],
        CAST(NULL AS int) AS [C1],
        [Extent3].[FunctionName] AS [FunctionName],
        cast(0 as bit) AS [C2],
        cast(1 as bit) AS [C3]
        FROM [dbo].[Employee] AS [Extent3]) AS [UnionAll1] ON [Extent1].[PersonID] = [UnionAll1].[CustomerID]

    A left outer join was done with a union of customer and employee. Also note the CASE statements in the main select statement.
    I leave it up to you to decide if such SQL statements are okay in your environment. I see no problem with them but I can see them growing pretty fast.

    Let's take a look at what happens if you only want your customers. The following Linq expression can be used:

    IQueryable<Customer> customers =
    from customer in context.Person.OfType<Customer>()
    select customer;

    When executed, the following SQL is executed:

    SELECT
    '0X0X' AS [C1],
    [Extent1].[CustomerID] AS [CustomerID],
    [Extent2].[Firstname] AS [Firstname],
    [Extent2].[Lastname] AS [Lastname],
    [Extent1].[CustomerDiscount] AS [CustomerDiscount]
    FROM [dbo].[Customer] AS [Extent1]
    INNER JOIN [dbo].[Person] AS [Extent2] ON [Extent1].[CustomerID] = [Extent2].[PersonID]

    All in all very straightforward.

    Wednesday, 02 January 2008 18:56:31 (Romance Standard Time, UTC+01:00)  #    Comments [11]  |  Trackback