PostSharp4EF: Automatically implement IPoco interfaces (for EF 3.5/VS2008)

This project uses PostSharp to post-compile your assemblies. When it encounters a simple attribute, it will implement everything needed to use it in EF: Typelevel attributes, EDMscalar attributes, changetracking and default values. This means there are no runtime performance penalties. See Introducing EF Contrib post for more detailed information about this project. The following supporting projects are included as well and will enable the use of full disconnected n-tier usage of your domain objects:
  • Circular Serializer: enables the serialization of object graphs (including circular references) with knowledge of 'original values'.
  • Editable Business Objects: does changetracking and provides the serializer with the correct values.

This project adds a compilation phase to your project. During that compilation phase, the metadata from your edmx file is used to alter the compiled code to actually implement all the requirements for a domain object to work with Entity Framework. This enables the developer to work with POCO (Plain Old Code Objects) objects that know nothing of the Entity Framework, in other words: they are Persistence Ignorant.

The project works together with 2 other projects (also included): Circular Serializer and Editable Business Objects. Together they offer effortless n-tier distributed usage of your domain layer, arguably the most important layer of your application. Read more about this here: full disconnected n-tier usage.

Reason of existence

In an agile design process, it is important to be able to work on a domain layer that is not weighed down by data access code. Ideally, one would like to be able to reuse the domain objects in other scenario's without having to make changes. Also, it should be simple to replace data-access code (for instance, to use another OR-mapper), without having to worry about how this affects the business layer.
This means that no data-access logic should invade the domain layer at all. Business objects focus solely on implementing business logic and validation.

The Entity Framework does not allow this in version 1. It does however present 3 interfaces (commonly known as the IPoco interfaces) that, when implemented, at least take away the need for a baseclass. The implementation of these interfaces is not easy and still invades the domain layer.

Example

Let's start by creating a Person object:
    [DataContract(Namespace = "myNamespace", Name = "Person")]
    public class Person
    {
        [DataMember]
        public int PersonID { get; set; }
        [DataMember]
        public string Firstname { get; set; }
        [DataMember]
        public string Lastname { get; set; }

    }


The next step is to add an attribute that will notify the postcompilation step to alter this object:
[assembly: Poco("InheritanceTypeConnection")]

This will trigger the following actions:
  • implementing IEntityWithChangeTracker, IEntityWithKey and IEntityWithRelationships. These are the IPoco interfaces that EF needs to work
  • put the EdmEntityType attribute on top of the class
  • put the EdmScalarProperty attributes on top of the properties
  • put EdmRelationShip attributes on the assembly (if needed)
  • put the EdmSchema attribute on the assembly

Then a few other interfaces are implemented, that are needed for the system to work.
  • the IUpdateComplexTypesWithTracker interface is used to facilitate complex types
  • the IGetChangeTracker interface is used to get to the changetracker
  • the IContextAware interface can be used to attach an object to the context (!) and prepare it for serialization (!)
  • the IRelationshipLoader interface can be used to load relationships
  • the IStorageAccess and ISerializationHelp interfaces are used during serialization

Behind the scenes, access to relationships are rewritten to use the Relationshipmanager, and setters of properties are intercepted to raise the proper events.

It is important to understand that this is never visible in Visual Studio. Your code remains untouched. The resulting dll is enhanced with these features

When we open the dll in reflector, we see the following:
[EdmEntityType(Name="Person", NamespaceName="Domain")]
public class Person : IPocoFacade, IComposed<IPocoFacade>, IUpdateComplexTypesWithTracker, IStorageAccess, IRelationshipLoader, ISerializationHelp
{
...... a lot of members left out .....
    // Properties
    [DataMember, EdmScalarProperty(IsNullable=false)]
    public string Firstname { get; set; }
    [DataMember, EdmScalarProperty(IsNullable=false)]
    public string Lastname { get; set; }
    [EdmScalarProperty(IsNullable=false, EntityKeyProperty=true), DataMember]
    public int PersonID { get; set; }
}

End result

The end result is that you are able to work with regular objects, without thinking about Entity Framework. This enables an agile work process.

Last edited Jan 9, 2011 at 8:37 PM by JulieLerman, version 2

Comments

riles01 Dec 25, 2008 at 8:35 PM 
This looks terrific! I suppose my only question is whether or not database field names must be used and, if so, are the field names case sensitive?