Tuesday, 29 April 2008

I've recently moved this blog to another host. Everything seems to work, except for access denied errors on the comments.

I'm using DasBlog which writes to the filesystem. I'm able to post new posts without problems, but comments don't work.

If you have any comments, feel free to email me. I've already received a few, and will be answering them.

[update: not sure why, but I removed the allcomments.xml, and there is no longer an error. However, no new 'allcomments.xml' file is created, so don't know what's up with that!]

Tuesday, 29 April 2008 14:33:19 (Romance Standard Time, UTC+01:00)  #    Comments [11]  |  Trackback
 Wednesday, 23 April 2008

Daniel Simmons commented on the next beta of EF where the team has worked with the WCF team to allow for better serialization (in an interoperable way) of complete graphs and relations. I'm very excited to hear that, but as Julie Lerman pointed out: it's also kind of frustrating for me. ;-)

As you know, I have 3 different pieces of technology that help make the possibility of n-tier disconnected scenario easy.

One of those pieces is the circular serializer, that was created to change the way WCF serializes circular references. However, it has grown to also support 'original' values.

My current plan is as follows:
I will wait to see how WCF serializes entity graphs in the next beta. I expect to see that my circular serializer is no longer necessary. Hopefully I will be able to remove it all together.
What will still be necessary though is getting the original values across the wire. So, I'll probably generate those properties inside of the classes themselves, negating the use of a surrogate serializer. Then, on the client, you will just be able to use your objects like before, and on the server you would notify the objectgraph of the need to fill the original values just before you return them. This might work out very well.

The use of a surrogate is actually what is stopping me from targeting Silverlight, so with a little luck, the changes in the next version will enable the use of Silverlight as well. I'm looking forward to it!

Wednesday, 23 April 2008 11:12:39 (Romance Standard Time, UTC+01:00)  #    Comments [9]  |  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:


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    {
  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();
  10     employees.ForEach(p => context.PrepareForSerialization(p)) ;
  11     return employees;
  12    }
  13   }


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:


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);
  7     context.SaveChanges();
  8    }
  10    string MsgOnWire = String.Empty;
  11    int id;
  12    using (InheritanceTypeConnection context = new InheritanceTypeConnection())
  13    {
  15     Einstein lead = new Einstein { Firstname = "Bill", Lastname = "G" };
  16     context.AddToPerson(lead);
  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);
  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);
  24     context.SaveChanges();
  25     id = e1.PersonID;
  27     MsgOnWire = context.Serialize(e1);  // we'll take mort as the graphroot (no importance)
  28    }
  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
  36    EmployeeClient teamlead = mClient.TeamLeader;
  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;
  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);
  48    // serialize
  49    MsgOnWire = mClient.SerializeForClient();
  52    using (InheritanceTypeConnection context = new InheritanceTypeConnection())
  53    {
  55     // deserialize
  56     Mort m = context.Deserialize<Mort>(MsgOnWire);
  58     context.SaveChanges();
  59    }

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
 Tuesday, 15 April 2008

I'm building a small sample for EFContrib, and thought it would be cool to use the new MVC framework 'Prism' for it. Prism is a new framework currently under development by the patterns and practices group. It is not feature complete and everything might change in the next drop. But, well, it's fun to see such a framework develop and how best to understand it, than by building something simple with it!

I'm trying to do something fairly basic: I have a view that has a button on it. If the button is pressed, a form should popup where we can search for employees. When the search is over, the result should be accessible by my controller.
At the same time though, I know that I'm going to have a detail screen as well with the same button on it. Here the button chooses a teamleader for the employee.

I want to define the command once, but need my controllers to behave differently. It's quite possible that I would be better off just creating two commands (one for the detail screen and one for the employee screen). You could argue that they perform different actions: choose an employee versus choose a teamleader.
But I don't swing that way and I feel it should be possible to have the same command on a lot of buttons and let the appropriate controller deal with it.

In the prism project are a few base classes for commands: the DelegateCommand and also the ActiveAwareDispatchCommand. As far as I can see, they allow a command to be hooked up by multiple views and allow controller to register their interest in them.
I created a static class with my 'ChooseEmployee' command:


    public static class EmployeeChooserCommands
        public static ActiveAwareMultiDispatchCommand ChooseEmployee = new ActiveAwareMultiDispatchCommand();

Now, my views couple their buttons to this command in the regular way.

In my definition of MVC a controller is responsible for the logic and thus handles this command.

        protected ActiveAwareDelegateCommand chooseEmployeeCommand;

It defines it's own command and in the ctor hooks it up:

            chooseEmployeeCommand = new ActiveAwareDelegateCommand(Choose, CanChoose);
            // register this instance on the global

The last line will make this controller react to executions of the command by every source.

This is the pattern that I see in the current Prism reference implementation project.

The fun thing about the ActiveAwareDelegate is the way you can set it as Active and not-Active. If it is not active, it will not be queried for canExecute information and its execute delegate will not be called.

So, what I did, was to let my views implement the IActiveAware interface and throw an event when they lose or get focus. The corresponding controllers react to it in this way:

        void view_IsActiveChanged(object sender, EventArgs e)
            chooseEmployeeCommand.IsActive = view.IsActive;

Setting the command to only be active when the view is active.
Downside here is that if one view is active, it gets to decide on the canExecute result, but all buttons in all views will react to it: clearly not what we want.

So, I feel I'm on the wrong track here. I really miss being able to set some sort of 'affinity' to the RegisterCommand method. I would like to let that method know I'm interested in commands where the source is equal to my view. But then again, maybe I should just create different commands :-)

Tuesday, 15 April 2008 17:50:12 (Romance Standard Time, UTC+01:00)  #    Comments [14]  |  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:


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.


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; }
  16   [DataMember]
  17   public ICollection<Enrollment> Enrollments { get; set; }
  18   [DataMember]
  19   public ICollection<Course> Courses { get; set; }
  21 }
  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; }
  41   [DataMember]
  42   public ICollection<Enrollment> Enrollments { get; set; }
  43   [DataMember]
  44   public ICollection<Person> Persons { get; set; }
  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; }
  61   [DataMember]
  62   public ICollection<Course> Courses { get; set; }
  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; }
  73   [DataMember]
  74   public Course Course { get; set; }
  75   [DataMember]
  76   public Person Person { get; set; }
  78 }
  79 }

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:


(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.*")]
#if Client
[assembly: EditableBusinessObjectAttribute(AttributeTargetAssemblies="Domain", AttributeTargetTypes="Domain.*")]
[assembly: CreateSerializeSurrogate("EditableBusinessObjects.Postsharp.Public.IEditableBusinessObject, EditableBusinessObjects.Postsharp.Public", AttributeTargetAssemblies="Domain", AttributeTargetTypes="Domain.*")]

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);
  7   [OperationContract]
  8   void SavePerson(Person person);
  10   [OperationContract]
  11   IList<Course> GetCourses();
  13   [OperationContract]
  14   IList<Department> GetDepartments();
  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();
  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     }
  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");
  29      }
  30     }
  32     ((IContextAware)p).CreateSerializableState(context);
  34     return p;
  35    }
  37   }
  40   public void SavePerson(Person person)
  41   {
  42    using (SchoolContext context = new SchoolContext())
  43    {
  44     ((IContextAware)person).AttachGraphToContext(context, entity => entity.GetType().Name);
  46     context.SaveChanges();
  47    }
  48   }
  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;
  59    }
  60   }
  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   }
  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();
  4    IList<Department> departments = svc.GetDepartments();
  6    Person Fadi = svc.GetPerson(4, false, false);
  8    Console.WriteLine(String.Format("Working on {0} {1}, Hired at {2:D}",
  9     Fadi.FirstName, Fadi.LastName, Fadi.HireDate));
  10    Console.WriteLine();
  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());
  15    Console.WriteLine("I can bug you for a title as well, can't I?");
  16    string title = Console.ReadLine();
  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);
  24    Fadi.FirstName = "Fadi,Changed at " + DateTime.Now.ToShortTimeString();
  27    Fadi.Courses.Add(newCourse);
  30    svc.SavePerson(Fadi);
  32    Console.WriteLine("Finished, go check your database. I added the new course to department:" + newCourse.Department.Name);
  33    Console.ReadLine();
  36   }

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

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

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

kick it on DotNetKicks.com

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

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

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

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