With the release of EntityFramework v1 and lack of features such as Lazy Loading and Persistence Ignorance leading to Vote of No Confidence resulted the team working on Entity Framework project to actually change route and as the result, a lot of improvements has been made in EntityFramework v4. Wait a second…What happened to v2 and v3, you might ask? Well, EntityFramework vNext that will be released with .NET Framework 4 is named EntityFramework v4, so you didn’t miss anything. Let’s see how PI works in this version.

I’m using the bits included in Visual Studio 2010 Beta 2 with additional features included in Entity Framework 4 CTP 2 (not included in VS 2010) which you can download here</a>.

No base class required

Unlike previous version, your entity classes may have no base class at all and you don’t have to implement a lot of interfaces to make your POCO class an entity. Whether you’re designing your models in code or using the model designer, the choice for a base class on your entities is an optional one. This makes things a lot easier and you’ll end up with a much simpler domain model.

Entity Properties

All Code Development

Also referred to as Model First, this is where you create the domain model without actually using a designer and use code instead. You now do this by creating regular Plain Old CLR Objects (POCO) to act as your domain entities. The good thing is, you don’t need XML mapping files, you don’t need to decorate your model with cluttering Attributes: just bare POCO classes will do.

Creating a domain model is self explanatory. Here’s the code for a simple Product / Category model:

public class Category
{
    public int Id
    {
        get; set;
    }

    public string Name
    {
        get; set;
    }

    public List Products
    {
        get; set;
    }
}

public class Product
{
    public int Id
    {
        get; set;
    }

    public string Name
    {
        get; set;
    }
    
    public int CategoryId
    {
        get; set;
    }

    public Category Category
    {
        get; set;
    }
}

To query your entity classes you need to create another class that inherits from ObjectContext. This model defines your interactions with your entities and returns your domain entities as a new queryable interface which is IObjectSet<T>. This new interface is made up of IQuerable<T> plus Attach, Detach, Add and Delete functions. Should you need to keep your domain model clean, you can move this class out of your main domain model assemblies:

public class SalesObjectContext : ObjectContext
{
    public SalesObjectContext(EntityConnection connection) : base(connection)
    {
    }

    private ObjectSet _categorySet;
    public IObjectSet Categories
    {
        get
        {
            return _categorySet ?? (_categorySet = CreateObjectSet());
        }
    }

    private ObjectSet _productSet;
    public IObjectSet Products
    {
        get
        {
            return _productSet ?? (_productSet = CreateObjectSet());
        }
    }
}

What about Meta-Data?

As in almost any ORM framework, you need “some” meta-data regarding your domain entities. These metadata are normally data-centric things such as PrimaryKeys, Constraints, Indexes, etc. so are not considered as a part of the domain model, but are needed anyway. Since there’s no EDMX file, how does EntityFramework know about such things? The answer is: It does not. We need to create some mapping files for these metadata. This is like how FluentNHibernate works.

First create your mapping classes using the Fluent API available in EF v4:

public class ProductMapping : EntityConfiguration
{
    public ProductMapping()
    {
        HasKey(x => x.Id);

        Property(x => x.Id).IsIdentity();
        Property(x => x.Name).HasMaxLength(20).IsRequired();

        Relationship(x => x.Category).HasConstraint((x, y) => x.CategoryId == y.Id);
    }
}

Although there could be some improvements here, things such as support for other PrimaryKey generation other than Identity, adding prefix / suffix to table names, etc. it works for now. Finally, you need to register these mappings when creating the ObjectContext:

public static void FindDVDs()
{
    var conn = new SqlConnection(); //or any DbConnection instance
    var builder = new ContextBuilder();

    builder.Configurations.Add(new ProductMapping());
    builder.Configurations.Add(new CategoryMapping());

    using(var ctx = builder.Create(conn))
    {
        var dvds = from c in ctx.Categories
                   where c.Name == "DVDs"
                   select c;

        var products = from p in ctx.Products
                       where p.Category == dvds
                       select p;
    }
}

Closing

No doubt, there’s been a lot of improvements in EntityFramework v4 and it is going the right direction, but a lot needs to be done before I can call it a robust, full feature and more importantly mature framework, but it is not a released product yet. In next port, I’ll add some IoC to the pot and show how to implement repository pattern using EF v4.