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
 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
 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
 Monday, 17 March 2008

I'll probably dedicate a bigger post to this soon, but I wanted to show you a domainmodel, some code and the xml it generates.
What you see here is two attributes that take on quite a bit of work.
EditableBusinessObject implements IEditableObject for you and also allows you to copy the currentvalues to a loadedvalues state.
CreateSerializeSurrogate generates a surrogate class that knows how to deal with loadedvalues and with circular references.
Together, they form the backbone of the client-side of your domainmodel.

Here is an example.

DomainModel:
(notice this is the full class, no other properties are here)

  0 [EditableBusinessObject]
  1 [CreateSerializeSurrogate]
  2 [Serializable]
  3 [DataContract(Namespace = "myNamespace", Name = "Person")]
  4  public class Person
  5 {
  6   [DataMember]
  7   public int IntProperty { get; set; }
  8
  9   [DataMember]
  10   public string StringProperty { get; set; }
  11
  12   [DataMember]
  13   public string StringProperty2 { get; set; }
  14
  15   int neverSetInt;
  16   [DataMember]
  17   public int NeverSetInt
  18   {
  19    get
  20    {
  21     return neverSetInt;
  22    }
  23    set { neverSetInt = value; }
  24   }
  25
  26   [DataMember]
  27   public List<string> StringLijst { get; set; }
  28
  29   [DataMember]
  30   public List<int> IntLijst { get; set; }
  31
  32   public Person()
  33   {
  34    StringLijst = new List<string>();
  35    IntLijst = new List<int>();
  36   }
  37
  38 }
  39

Some testcode:
(notice line 16 where we do a endEdit. If we had cancelled, we would've had a proper rollback)

  0    Person p = new Person();
  1    p.IntProperty = 1;
  2    p.StringProperty = "Ruurd";
  3    p.StringProperty2 = "Boeke";
  4
  5    p.StringLijst.Add("a");
  6    p.IntLijst.Add(1);
  7
  8    (p as IEditableBusinessObject).CopyCurrentToLoaded();
  9
  10    (p as IEditableBusinessObject).BeginEdit();
  11
  12    p.IntLijst.Add(2);
  13    p.StringLijst.Add("b");
  14    p.StringProperty = "Ruurd Boeke";
  15
  16    (p as IEditableBusinessObject).EndEdit();
  17
  18    DataContractSerializer s = new DataContractSerializer(p.GetType(), null, int.MaxValue, false, false, new SubstituteDomainDataContractSurrogate());
  19
  20    string outMessage = GetWellFormedToContract(p, s);

And the generated xml:
(notice how the lists and 'StringProperty' are changed, and see the original value).

<PersonSurrogate xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="myNamespace">
    <IntLijst xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <d2p1:int>1</d2p1:int>
        <d2p1:int>2</d2p1:int>
    </IntLijst>
    <IntProperty>1</IntProperty>
    <SerializationID>0</SerializationID>
    <StringLijst xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <d2p1:string>a</d2p1:string>
        <d2p1:string>b</d2p1:string>
    </StringLijst>
    <StringProperty>Ruurd Boeke</StringProperty>
    <StringProperty2>Boeke</StringProperty2>
    <OriginalValue_IntLijst xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <d2p1:int>1</d2p1:int>
    </OriginalValue_IntLijst>
    <OriginalValue_IntProperty>1</OriginalValue_IntProperty>
    <OriginalValue_StringLijst xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <d2p1:string>a</d2p1:string>
    </OriginalValue_StringLijst>
    <OriginalValue_StringProperty>Ruurd</OriginalValue_StringProperty>
    <OriginalValue_StringProperty2>Boeke</OriginalValue_StringProperty2>
</PersonSurrogate>

What is left, is deserializing, maybe propagating the beginedit commands to all children and then create the serverside EF variant.
Oh, and I don't like the originalValue representation. Maybe I'll generate a OriginalValue class to keep it tidy.

Monday, 17 March 2008 22:28:31 (Romance Standard Time, UTC+01:00)  #    Comments [11]  |  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
 Monday, 25 February 2008

This is the sixth 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 delves into using the weaver, to do some funky stuff for us!

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 compound attribute and how it goes about implementing interfaces on classes for you.

    We want to put custom attributes on our type that EF needs (the EDM scalar attributes on top of properties and the EDM type attribute that connects your type to a EDM type). Laos does not seem to have a ready-to-use aspect that provides that functionality, so we are going to need to hook into the weaver ourselves! How exciting!
    Thankfully, we can derive from TypeLevelAspectWeaver to make life easy enough.

    In the previous post, we hooked up the weaver, this post we are actually going to do stuff.

    The Implement method

    Our weaver derives from TypeLevelAspectWeaver, and thus can override the Implement() method. I have to do some stuff to get to your config file, using PostSharp to get the Path to the original App.Config. When I have that, I load it, and look at the connectionstring that matches the containername you have supplied the attribute. Then, I use the EntityConnectionBuilder to create a connection string and finally load in the metadata workspace from EDM. With the metadata in hand, I can start looking at the transformation I have to do.

    Setting EDMScalarAttributes

    I recently chatted with Gael (creator of PostSharp) and he assured me that there would be a highlevel method to add attributes to code. In this version of PostSharp, that is not directly possible (hence, the weaver we are using). So, we will do it ourselves.

    First, let's loop through all the properties defined on our supplied businessEntity:

      1             foreach (PropertyDeclaration prop in typeDef.Properties)
      2             {
      3                 EdmProperty memberProperty;
      4 
      5                 // find it as a member
      6                 memberProperty = entityType.Members.SingleOrDefault(edmprop => edmprop.Name.Equals(prop.Name)) as EdmProperty;
      7 
      8                 // it can easily be something else than an edm property
      9                 if (memberProperty != null)
     10                 {
     11                     // it might be a key property. I have not yet found a better way to determine if it is a keymember or not. This seems wastefull
     12                     prop.CustomAttributes.Add(
     13                         CreatePropertyAttribute(memberProperty,
     14                         (entityType.KeyMembers.SingleOrDefault(edmprop => edmprop.Name.Equals(prop.Name)) != null)));
     15 
     16                     continue;
     17                 }
    18             }

    I use a bit of Linq to check if this a propety is a key, and call my CreatePropertyAttribute method:

      1         CustomAttributeDeclaration CreatePropertyAttribute(EdmProperty edmProperty, bool IsKeyProperty)
      2         {
      3             CustomAttributeDeclaration attr = new CustomAttributeDeclaration(edmScalarPropertyAttribute);
      4 
      5             // nullable
      6             attr.NamedArguments.Add(
      7                 new MemberValuePair(MemberKind.Property,
      8                     0,
      9                     "IsNullable",
     10                     new SerializedValue(
     11                         SerializationType.GetSerializationType(this.module.FindType(typeof(bool), BindingOptions.Default)),
     12                         edmProperty.Nullable)
     13                         ));
     14 
     15             // since we need to set the ordinal, take care to set this property last!
     16             if (IsKeyProperty)
     17             {
     18                 attr.NamedArguments.Add(
     19                     new MemberValuePair(MemberKind.Property,
     20                         1,
     21                         "EntityKeyProperty",
     22                         new SerializedValue(
     23                             SerializationType.GetSerializationType(this.module.FindType(typeof(bool), BindingOptions.Default)),
     24                             true)
     25                             ));
     26             }
     27 
     28             return attr;
    29         }

    As you can see, it get's a little bit more complicated. We need to add a custom attribute, but to get it, we need to have a constructor for the attribute. I already have it cached: at line 3 the cached IMethod is given to the PostSharp CustomAttributeDecaration class. I got to the ctor like this:

                edmScalarPropertyAttribute = module.FindMethod(typeof(EdmScalarPropertyAttribute).GetConstructor(System.Type.EmptyTypes), BindingOptions.Default);
    

    We use PostSharp to find the constructor in the module.

    With the constructor, we can create a customAttributeDeclaration and from there we can add namedArguments. Note, that here again, we use PostSharp to find types for us. Kind of confusing, but it does provide a consistent way to do things. You could use it to call your own methods as well (!).

    I do the same for the attribute that needs to be placed on the complete type, and we are ready!

    Default values

    In the EF designer, you have the ability to specify default values for properties. I needed to mimic this functionality for this project, so I got to work. It seemed quite simple, because I could get to the fields without a problem. However, fields are initialized in the ctor of your type (thank you reflector). So more work was needed.

    First, I wanted to reuse this weaver, and wanted the weaver to add IL methods in the constructor. To do that, I implemented the ITypeLevelAdvice interface and added this line to the end of the implement():

                // make sure this class is called to weave
    
                this.Task.TypeLevelAdvices.Add(this);

    Implementing the ITypeLevelAdvice gives us the opportunity to supply some  information about what we want to do exactly:

            #region ITypeLevelAdvice Members
    
            public JoinPointKinds JoinPointKinds { get { return JoinPointKinds.AfterInstanceInitialization; } }
    
            public TypeDefDeclaration Type { get { return (TypeDefDeclaration)this.TargetElement; } }
    
            #endregion
    
            #region IAdvice Members
    
            public int Priority
    
            {
    
                get { return 0; }
    
            }
    
            public bool RequiresWeave(PostSharp.CodeWeaver.WeavingContext context)
    
            {
    
                return true;
    
            }
    
            #endregion

    As you can see, I want to use the AfterInstanceInitialization joinpoint. In other words, I want to be able to weave code, at that moment.

    What to weave?? I know everything about my businessentity, but I only know which properties need default values. So I want to come up with some basic rules about which field belongs to a certain propertyname:

      1             #region set default values. not yet emitting the instruction, but waiting for the Weave method
    
      2             foreach (FieldDefDeclaration field in typeDef.Fields)
    
      3             {
    
      4                 // we have to make concessions: we do not know how to find the field with the property exactly
    
      5                 EdmProperty memberProperty;
    
      6 
    
      7                 // find it as a member
    
      8                 // the rules: the field must match the ending of the propertyname. So underscore is okay
    
      9                 memberProperty = entityType.Members.SingleOrDefault(edmprop => field.Name.EndsWith(edmprop.Name, StringComparison.OrdinalIgnoreCase) ) as EdmProperty;
    
     10 
    
     11                 // in case that didn't match, try the autogenerated fieldname
    
     12                 if (memberProperty == null)
    
     13                 {
    
     14                     memberProperty = entityType.Members.SingleOrDefault(edmprop => (field.Name.IndexOf("<" + edmprop.Name + ">") == 0)) as EdmProperty;
    
     15                 }
    
     16 
    
     17                 // if this field belongs to a edm property, we can check for it's default value
    
     18                 if (memberProperty != null)
    
     19                 {
    
     20                     FieldsNeedingDefaultValue.Add(field, memberProperty.Default);
    
     21                 }
    
     22 
    
     23             }  
    24             #endregion

    I use two rules: if the field ends with the same name as the property, then this field belongs to that property. Another rule is, to look at the naming scheme that the compiler uses when it generates auto properties: <Propertyname>_k_backingfield;. Since that is how we will most likely use this whole project, I want to also support that.
    I build up a default value dictionary that I use in a later stadium.

    The weave method will be called when our joinpoint has been reached.

      1         public void Weave(PostSharp.CodeWeaver.WeavingContext context, InstructionBlock block)
    
      2         {
    
      3             foreach (FieldDefDeclaration field in FieldsNeedingDefaultValue.Keys)
    
      4             {
    
      5                 object value = FieldsNeedingDefaultValue[field];
    
      6 
    
      7                 if (value == null)
    
      8                     continue;
    
      9 
    
     10                 // the context is the ctor because we only use the joinpoint AfterinstanceInitialization
    
     11                 InstructionSequence sequence = context.Method.MethodBody.CreateInstructionSequence();
    
     12                 block.AddInstructionSequence(sequence, NodePosition.Before, null);
    
     13                 context.InstructionWriter.AttachInstructionSequence(sequence);
    
     14                 InstructionWriter writer = context.InstructionWriter;
    
     15 
    
     16                 if(value is int)
    
     17                 {
    
     18                             writer.EmitInstruction(OpCodeNumber.Nop);
    
     19                             writer.EmitInstruction(OpCodeNumber.Ldarg_0);
    
     20                             writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, (int)value );
    
     21                             writer.EmitInstructionField(OpCodeNumber.Stfld, field);                }
    
     22                 else if (value is string)
    
     23                 {
    
     24                             writer.EmitInstruction(OpCodeNumber.Nop);
    
     25                             writer.EmitInstruction(OpCodeNumber.Ldarg_0);
    
     26                             writer.EmitInstructionString(OpCodeNumber.Ldstr, (string)value);
    
     27                             writer.EmitInstructionField(OpCodeNumber.Stfld, field);                }
    
     28                 else
    
     29                 {
    
     30                     // TODO: implement other value types
    
     31                     throw new NotImplementedException(String.Format("No IL default implemented for type {0}", value.GetType()));
    
     32                 }
    
     33 
    
     34                 writer.DetachInstructionSequence(true);
    
     35             }
    
     36 
    
    37         }

    Again, Gael has assured me that a highlevel functionality will be created to easily set default values. I do not like to work with a big IF statement to inject different IL instructions per type, but that's it for now....

    I just use reflector, in IL viewing mode, to see how I should initialize a certain type, and off we go.

     

    This is the end of this series. I hope you enjoyed it.

    The following things still have to be done:

    • PostSharp can now be installed without using the GAC. I think people feel more at ease just using an external assembly, so I will change the EFContrib project to support this.
    • Relationships and complex types need to be supported
    • Obviously, the other default values need to be supported.

    I'll keep you updated on how that progresses!
    I hope this series has given you some ideas on how to use postcompiling in your own project. Let it make your life easier and your code cleaner.

  • Monday, 25 February 2008 15:56:01 (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  Trackback
     Friday, 22 February 2008

    This is the fifth 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 weaver, that will do exciting stuff for us.

    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 compound attribute and how it goes about implementing interfaces on classes for you.

    This post will look at how we are going to hook up a weaver to do more complex stuff, not directly supported by the provided Laos aspects.

    But first I want to clear up a statement I made here: 'I found it wildly confusing the first time I came across the two parts of postsharp. Laos is such a high-level abstraction, that you use it quite differently from Core. In the latter, you have to spinup your own weaver, in Laos you do not ever see a weaver. '
    It is not true that you do not ever see a weaver when using Laos. I should have been more clear: Laos offers a great deal of functionality that you can use without going into a weaver.

    We want to put custom attributes on our type that EF needs (the EDM scalar attributes on top of properties and the EDM type attribute that connects your type to a EDM type). Laos does not seem to have a ready-to-use aspect that provides that functionality, so we are going to need to hook into the weaver ourselves! How exciting!
    Thankfully, we can derive from TypeLevelAspectWeaver to make life easy enough.

    Hooking up a weaver

    The cool thing about using the weaver is, that you can put it in it's own assembly and not have to reference it in the assemblies that you are postcompiling. That is quite important, because the weaver depends on PostSharp.Core and there is another license attached to it.
    The PocoAttribute adds an aspect to the collection, like it did for the other aspects:

      1 public override void ProvideAspects(object element, LaosReflectionAspectCollection collection)
      2         {
      3             // Get the target type.
      4             Type targetType = (Type)element;
      5
      6 ....
    10             // inspect the complete class and add EDM scalar attributes to the properties
    11             collection.AddAspect(targetType, new EDMAttributesSubAspect(this.EDMContainerName, Name, NamespaceName, PathToConfigFile));
    .....
    12 }

    At line 11, the EDMAttributesSubAspect is added. This means that when Laos is ready to start working, it will check that aspect to see what it should do. Let's look at it now:

        [Serializable]
        internal class EDMAttributesSubAspect : ILaosTypeLevelAspect
        {
            #region fields and properties
            internal string EDMContainerName { get; set; }

            internal string TypeName { get; set; }
            internal string NamespaceName { get; set; }
            internal string PathToConfigFile { get; set; }
            #endregion

            #region ctor
            /// <summary>
            /// ctor
            /// </summary>
            /// <param name="EDMContainerName">the container name</param>
            /// <param name="NamespaceName">namespacename, can be null</param>
            /// <param name="TypeName">typename, can be null</param>
            public EDMAttributesSubAspect(string EDMContainerName, string TypeName, string NamespaceName, string PathToConfigFile)
            {
                this.EDMContainerName = EDMContainerName;
                this.TypeName = TypeName;
                this.NamespaceName = NamespaceName;
                this.PathToConfigFile = PathToConfigFile;
            } 
            #endregion

            #region ILaosTypeLevelAspect Members

            public void CompileTimeInitialize(Type type)
            {
            }

            public bool CompileTimeValidate(Type type)
            {
                return true;
            }

            public void RuntimeInitialize(Type type)
            {
            }

            #endregion

            #region ILaosWeavableAspect Members

            public int AspectPriority
            {
                get { return int.MinValue; }
            }

            #endregion 

        }

    You might be surprised to hear that this is the complete aspect!! Nothing that hints at what is to come.

    When such a thing happens, you might be stumped. But obviously you will immediately think to check the assemblyinfo file of the PostSharp4EF assembly:

    [assembly: PostSharp.Extensibility.ReferencingAssembliesRequirePostSharp("PocoTypeWeaver", "EntityFrameworkContrib.PostSharp4EF.Weaver")]
    [assembly: InternalsVisibleTo("EntityFrameworkContrib.PostSharp4EF.Weaver")]

    Okay, I was kidding. You wouldn't have thought of that. ;-)

    The first statement there, instructs PostSharp to look for a plugin, with name PocoTypeWeaver to process all assemblies that are referencing this assembly. It is just another way of expressing requirements. I could have put that inside the attribute. But I did not.

    The plugin file can be found in the weaver assembly. It is just a normal text file with naming convention that matches the entire assembly name + "psplugin". The contents of that file:

    <?xml version="1.0" encoding="utf-8" ?>
    <PlugIn xmlns="http://schemas.postsharp.org/1.0/configuration">
      <TaskType Name="PocoTypeWeaver" 
                Implementation="EntityFrameworkContrib.PostSharp4EF.Weaver.PocoEDMAttributesWeaverFactory, EntityFrameworkContrib.PostSharp4EF.Weaver">
      </TaskType>
    </PlugIn>

    Here you will see a task PocoTypeWeaver and a reference to an implementation of a weaver factory. So, our PocoAttribute needs the pocoTypeWeaver and it can get one through the use of a factory. But, since your client assembly will not have a reference to this weaver assembly (which contains this mapping file), we need some way to tell it where to look. Enter the psproj file that was put inside your client assembly:

    <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>

    This psproj file is used by postsharp to extend it's searchpath. This means that on machines that are building the solution, you will need to supply some path where PostSharp can find the just mentioned psplugin file.

    Please note: there are other ways to configure the searchpath and possibly better ways to setup a system like this. There is a default searchpath and you could also put your plugin file there.

    The weaver factory
        public class PocoEDMAttributesWeaverFactory : Task, ILaosAspectWeaverFactory
        {

            #region ILaosAspectWeaverFactory Members
            /// <summary>
            /// creates the weaver
            /// </summary>
            /// <param name="aspect">the EDMAttributesSubAspect that instantiated this factory</param>
            /// <returns>the weaver that will do the lowlever hardcore work</returns>
            public LaosAspectWeaver CreateAspectWeaver(PostSharp.Laos.ILaosAspect aspect)
            {
                if (aspect is EDMAttributesSubAspect)
                {
                    EDMAttributesSubAspect edmAttributesAspect = (EDMAttributesSubAspect)aspect;
                    return new PocoEDMAttributesWeaver(edmAttributesAspect.EDMContainerName);
                }

                return null;
            }

            #endregion
        }

    Nothing special there. Using a factory allows you to supply different weavers for different aspects.

    So, to recap: we attached a plugin that did not do much itself. We used the assemblyinfo to tell PostSharp it should always use a certain task when compiling assemblies that are referencing our attribute assembly. We used the psproj file to make PostSharp search in the right spot and we used a psplugin file to tell map the task name to an actual factory.
    The factory creates our weaver, and we will discuss that in the next post!

  • Friday, 22 February 2008 10:41:17 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback
     Thursday, 21 February 2008

    Just a short message to let everyone know I have built the first version of default value support for efcontrib.

    I will follow up with a bigger post on the limitations. For now, only ints and strings will be processed.

    Thursday, 21 February 2008 16:44:26 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback

    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
     Wednesday, 20 February 2008

    This is the second 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 a 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
  • 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.
    Post 1 introduced the project and post 2 introduced PostSharp.

    The Compound aspect

    I have created an attribute class that can be placed on top of other classes, like so:

        /// <summary>
        /// <para>
        /// Attribute that can be used to decorate normal POCO classes with. It is used to start off a post compilation phase
        /// that will modify the IL of the class. After this phase, the class will implement:
        /// <list type="">
        /// <item>INotifyPropertyChanged</item>
        /// <item>IEntityWithChangeTracker</item>
        /// <item>IEntityWithKey</item>
        /// <item>IEntityWithRelationships</item>
        /// </list>
        /// </para>
        /// <para>
        /// It will also place EDMScalarattributes on your properties.
        /// </para>
        /// <para>This results in a type that is completely ready for consumption by the EntityFramework</para>
        /// </summary>
        [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
        [MulticastAttributeUsage(MulticastTargets.Class, AllowMultiple = false)]
        public sealed class PocoAttribute : CompoundAspect
        {
    ... implementation
        }

    As you can see it inherits from the compound aspect class, from the PostSharp.Laos assembly.

    The compound aspect basically allows you to define other aspects to do the job for you. This is very nice when you want to do more things, but only want to use one aspect.

    By overriding the ProvideAspects method, we can add our other aspects:

      1         public override void ProvideAspects(object element, LaosReflectionAspectCollection collection)
      2         {
      3             // Get the target type.
      4             Type targetType = (Type)element;
      5
      6             // implement the INotifyPropertyChanged interface on the class
      7             collection.AddAspect(targetType, new AddNotifyPropertyChangedInterfaceSubAspect());
      8             // implement the three IPOCO interfaces on the class
      9             collection.AddAspect(targetType, new PocoInterfacesSubAspect());
    10             // inspect the complete class and add EDM scalar attributes to the properties
    11             collection.AddAspect(targetType, new EDMAttributesSubAspect(this.EDMContainerName, Name, NamespaceName, PathToConfigFile));
    12
    13             // iterate the properties
    14             foreach (PropertyInfo property in targetType.UnderlyingSystemType.GetProperties())
    15             {
    16                 if (property.DeclaringType == targetType && property.CanWrite)
    17                 {
    18                     MethodInfo method = property.GetSetMethod();
    19
    20                     if (!method.IsStatic)
    21                     {
    22
    23                         // throw notifypropertychanged events
    24                         collection.AddAspect(method, new OnPropertySetNotifyPropertyChangedSubAspect(property.Name, this.AspectPriority));
    25
    26                         // TODO: possibly refactor to only include edm properties
    27                         // call the changetracker
    28                         collection.AddAspect(method, new OnPropertySetChangeTrackSubAspect(property.Name, this.AspectPriority));
    29                     }
    30                 }
    31             }
    32         }

    As you can see, on line 4 I cast the element parameter to a type. That is the type we have adorned with our attribute (your 'Person' Poco class, for instance). Then, I specify that I want 3 other aspects to work on this type!

    • The AddNotifyPropertyChangedInterfaceSubAspect, will implement the INotifyPropertyChangedInterface. (note: this aspect is added just for simplicity, it has nothing to do with IPoco, so I might remove it).
    • The PocoInterfaceSubAspect, will implement the 3 interfaces (see following post)
    • The EDMAttributesSubAspect, will put EDMScalar attributes on top of our properties, needed by EF to do it's job

    After that, I loop through the properties in our targetType and add aspects to their setters. These will inject methods into the setters to throw the PropertyChanged event and let the EF changetracker know that the property was changed.

    That's all the work this compound aspect does. It just provides aspects to the correct codeblocks. The real work is done inside of these aspects and will be explained in following posts.

    Wednesday, 20 February 2008 13:34:36 (Romance Standard Time, UTC+01:00)  #    Comments [5]  |  Trackback
     Tuesday, 19 February 2008

    This is the second 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 a 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 quickly introduces PostSharp, before we move on to the real stuff!

    The full table of contents:

    PostSharp

    The PostSharp home introduces PostSharp as follows:

    PostSharp is a tool that can reduce the number of lines of code and improve its logical decoupling. Therefore its helps you delivering higher stability, cleaner design, and cheaper source code maintenance

    And best of all, PostSharp is free and open source. Yes, even for commercial use

    Basically, it allows you to use attributes on top of code to indicate that after the normal visual studio compilation, PostSharp should do 'something' to the code. That 'something' could be anything you want. The result is a compiled assembly that does more than you would expect from the sourcecode. This is a good thing, when you have 'code noise': code that might be important, but distracts from the real work.

    Code noise could be your logging mechanism, or your transaction mechanism. In my case, I did not want to implement the IPoco interfaces that EntityFramework needs, in order to make my business objects work with EntityFramework. I want my business objects to represent a person, car or whatever, and not have to deal with the data access logic at all.

    The simplest example you can think of, is shown on the frontpage:

    public class SimplestTraceAttribute : OnMethodBoundaryAspect 

      public override void OnEntry( MethodExecutionEventArgs eventArgs) 
      { 
        Trace.TraceInformation("Entering {0}.", eventArgs.Method); 
        Trace.Indent(); 
      } 
      public override void OnExit( MethodExecutionEventArgs eventArgs) 
      { 
        Trace.Unindent(); 
        Trace.TraceInformation("Leaving {0}.", eventArgs.Method); 
      } 
    }

    By adding an [SimplestTrace] attribute on top of your code, you will have instant tracing information, without actually seeing it in your code. The fun thing about PostSharp is, that this code is actually in your assembly after post-compilation, as opposed to other AOP frameworks, that will do it at runtime.

    Laos versus Core
    PostSharp offers a full representation of your code, a bit like reflection. But it can be hard to work with. That is why PostSharp Laos was created. Laos is a 'plugin' on the core functionality that abstracts away most of the hard stuff, and leaves you with ready to implement aspects.

    I found it wildly confusing the first time I came across the two parts of postsharp. Laos is such a high-level abstraction, that you use it quite differently from Core. In the latter, you have to spinup your own weaver, in Laos you do not ever see a weaver.
    (A weaver is a class that will actually inject IL methods into your assembly.)

    When you use Laos, some smart hooks exist to use it's own weaver. That weaver knows how to deal with Laos Aspects. And so, you can use the Laos abstractions without any knowledge about IL or weaving.

    The shown example uses the OnMethodBoundaryAspect, from Laos. The Laos weaver will inject the necessary IL methods on every method (that matches your desire to trace it) to call the OnEntry and the OnExit methods you defined. There are quite a few aspects ready to inherit from. I urge you to look at the documentation to find out which.

    If you were to implement that functionality using the Core library, you would have to inject all the IL yourself. It would however, give you the opportunity to actually inject the Trace calls into the methods, instead of the easier method calls.

    One very interesting aspect that Laos offers, is the CompositionAspect, which allows you to set a specific interface to implement and give an implementation object that is called for every defined method on the interface. I use it for the three IPoco interfaces.

    In short: Laos is a very high-level abstraction that will get you very far. In some cases you need to take it a little further, and you will need Core.

     

    In the next couple of posts, I will show both the Laos aspects and the Core aspect, how they were applied and how they do their job.

    Tuesday, 19 February 2008 12:28:26 (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  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