Entity Framework 4.0 Beta 1 – POCO Enum support?

One of the things that has not made it into Entity Framework 4.0 beta 1 is Enum support and it is not planned for EF4.

This seems like a strange decision, as it is wrong and not POCO at all if you have to change your classes to work around the lack of enum support in your persistance layer.

Around the internet people suggest that you can just make the property private, and then create a public property that exposes your value as your enum. But that is not quite the solution, as this is not going to work in Linq queries that execute at database level.

While I was still trying to work around this, I came across this post by Alex James that does exactly what I was attempting: to fake enum support.

Lets see how this will look if we implement our Status property on the Order entity to be an enum.

The first thing we are going to do, is to change our Status property in the EF model to be a complex type. We can do that in the designer.

image

First of all we create the complex type. Right click “Complex Types” in the model browser and choose “Create Complex Type”. We name it OrderStatusWrapper and add a scalar Int32 property called “Value” to it.

Then we delete the scalar Status property from the Order entity, and add a complex property instead. We name it Status like the old one, and in properties we set the type to “OrderStatusWrapper”. If we build now, the validator will complain that we forgot to map the property, so we get the table mapping window, and map the Status integer to the “Value” integer on our complex property.

image

 

 

 

 

 

 

 

 

 

 

Now we add the enum as usually:

    3 public enum OrderStatus

    4 {

    5     OrderCreated,

    6     OrderPayed,

    7     OrderShipped

    8 }

Now we have to implement our OrderStatusWrapper, and make it do some work behind the scenes for us:

    1 

    2 public class OrderStatusWrapper

    3 {

    4     private OrderStatus _status;

    5 

    6     public int Value

    7     {

    8         get { return (int)_status; }

    9         set { _status = (OrderStatus)value; }

   10     }

   11     public OrderStatus EnumValue

   12     {

   13         get { return _status; }

   14         set { _status = value; }

   15     }

   16 

   17     public static implicit operator

   18         OrderStatusWrapper(OrderStatus status)

   19     {

   20         return new OrderStatusWrapper { EnumValue = status };

   21     }

   22 

   23     public static implicit operator

   24         OrderStatus(OrderStatusWrapper statusWrapper)

   25     {

   26         if (statusWrapper == null) return

   27             OrderStatus.OrderCreated;

   28         else return statusWrapper.EnumValue;

   29     }

   30 }

   31 

To do this we need to do an implicit operator overloading – that is an implicit conversion between OrderStatusWrapper and OrderStatus, creating the illusion that Status really is an OrderStatus enum value.

Now we can actually do this:

   24             Order o = new Order();

   25             o.CreatedDate = DateTime.Now;

   26             o.Status = OrderStatus.OrderCreated;

   27             o.Customer = custRep.First(x => x.Id == 1);

   28             orderRep.Add(o);

And we can use it in a query like so:

   24 var orders = from o in orderRep.GetAll()

   25              where o.Status == OrderStatus.OrderCreated

   26              select o;

This is a fairly decent workaround, but it still bothers me that we have to declare our property with the type of the wrapper, and that we have to clutter our code with wrappers. This is behaviour to accommodate our choice of ORM.

So we do need real enum support, but intill we do we seem to get by with this.

Resources:

Speaking at ANUG on Entity Framework 4.0 Beta 1 – Hands on look on the new bits

I will be speaking at the June meeting of ANUG covering the new bits in Entity Framework 4.0 Beta 1.

When:
25/6 18:00

Where:
Kamstrup A/S
Industrivej 28, Stilling
DK-8660 Skanderborg

Sign Up

It will be pretty hands on with focus on demoing the new stuff, starting out from the criticism of the first version of EF, to the wishlist for the next version.

Hope to see you there.

Entity Framework 4.0 Beta 1 – POCO, ObjectSet, Repository and UnitOfWork

In the old Entity Framework, creating a generic repository wasn’t impossible, but not really elegant either. Any way you looked at it, you needed to deal with strings to get it working.

Lets say you want to create an Add method on your repository, there was no way getting around something like this:

    6 

    7         objectContext.AddObject("OrderSet", newOrder)

    8 

So for each (base) entity you have in your conceptual model you have a corresponding EntitySet, and in EF1 you needed to pass in the string name of the entityset to add the object; the name is not necessarily the same as the name of the entity.

In a generic repository you would have to figure out the name of the current entityset – you can figure it out with a bit of reflection on the concrete ObjectContext, but its not pretty, errorprone and it took me a while to get there.

Enter ObjectSet<T>

Fortunately in EF4 the strongly typed properties on the ObjectContext for each EntitySet return ObjectSet<T> instead of ObjectQuery<T>. And since the ObjectContext also has a method called CreateObjectSet<T> you can instead do something like this:

    1 

    2 private IObjectSet<T> ObjectSet

    3 {

    4     get

    5     {

    6         if (_objectSet == null)

    7         {

    8             _objectSet = this.Context.CreateObjectSet<T>();

    9         }

   10         return _objectSet;

   11     }

   12 }

   13 

   14 public void Add(T entity)

   15 {

   16     this.ObjectSet.AddObject(entity);

   17 }

   18 

Notice the IObjectSet<T>  which is very handy as it enables you to fake the ObjectSet for testing for instance. Now to be fair, this is how it should have been in EF1, but on an optimistic note im happy its changed.

Repository<T>

In order to have the right context for testing EF4 properly with persistance ignorance and POCO we will set up a Repository and UnitOfWork pattern for the OrderModel project i did in my previous EF4 post. Im not going to cover every detail of this, but I will run through the setup, and then you can get the code and have a closer look on your own.

First i set up the repository contract and create an IRepository<T> where T is a POCO class.

    1 

    2 public interface IRepository<T> where T : class

    3 {

    4     IQueryable<T> GetQuery();

    5 

    6     IEnumerable<T> GetAll();

    7     IEnumerable<T> Find(Func<T, bool> where);

    8     T Single(Func<T, bool> where);

    9     T First(Func<T, bool> where);

   10 

   11     void Delete(T entity);

   12     void Add(T entity);

   13     void Attach(T entity);

   14     void SaveChanges();

   15 }

   16 

Next we will define a generic repository for the Entity Framework that implements IRepository<T>:

    1 

    2 public class EFRepository<T> : IRepository<T> where T : class

    3 {

    4     ObjectContext _context;

    5     IObjectSet<T> _objectSet;

    6 

    7     private ObjectContext Context

    8     {

    9         get

   10         {

   11             if (_context == null)

   12             {

   13                 _context = GetCurrentUnitOfWork

   14                     <EFUnitOfWork>().Context;

   15             }

   16             return _context;

   17         }

   18     }

   19 

   20     private IObjectSet<T> ObjectSet

   21     {

   22         get

   23         {

   24             if (_objectSet == null)

   25             {

   26                 _objectSet = this.Context

   27                     .CreateObjectSet<T>();

   28             }

   29             return _objectSet;

   30         }

   31     }

   32 

   33     public TUnitOfWork GetCurrentUnitOfWork<TUnitOfWork>()

   34         where TUnitOfWork : IUnitOfWork

   35     {

   36         return (TUnitOfWork)UnitOfWork.Current;

   37     }

   38 

   39     public IQueryable<T> GetQuery()

   40     {

   41         return ObjectSet;

   42     }

   43 

   44     public IEnumerable<T> GetAll()

   45     {

   46         return GetQuery().ToList();

   47     }

   48 

   49     public IEnumerable<T> Find(Func<T, bool> where)

   50     {

   51         return this.ObjectSet.Where<T>(where);

   52     }

   53 

   54     public T Single(Func<T, bool> where)

   55     {

   56         return this.ObjectSet.Single<T>(where);

   57     }

   58 

   59     public T First(Func<T, bool> where)

   60     {

   61         return this.ObjectSet.First<T>(where);

   62     }

   63 

   64     public void Delete(T entity)

   65     {

   66         this.ObjectSet.DeleteObject(entity);

   67     }

   68 

   69     public void Add(T entity)

   70     {

   71         this.ObjectSet.AddObject(entity);

   72     }

   73 

   74     public void Attach(T entity)

   75     {

   76         this.ObjectSet.Attach(entity);

   77     }

   78 

   79     public void SaveChanges()

   80     {

   81         this.Context.SaveChanges();

   82     }

   83 }

   84 

Now thats pretty straight forward. The ObjectContext actually already works like a UnitOfWork, but in order to handle the lifespan of our ObjectContext we wrap it up in our own UnitOfWork implementation.

    1 

    2 public class EFUnitOfWork : IUnitOfWork, IDisposable

    3 {

    4     public ObjectContext Context { get; private set; }

    5 

    6     public EFUnitOfWork(ObjectContext context)

    7     {

    8         Context = context;

    9     }

   10 

   11     public void Commit()

   12     {

   13         Context.SaveChanges();

   14     }

   15 

   16     public void Dispose()

   17     {

   18         if (Context != null)

   19         {

   20             Context.Dispose();

   21         }

   22         GC.SuppressFinalize(this);

   23     }

   24 }

   25 

IUnitOfWork consists of the method  Commit, and in our concrete implementation we save changes on our current ObjectContext on commmit.

To handle units of work we implement a static class that handles both the case of a webcontext and a multithreaded non web context. The ObjectContext is not threadsafe, so we need to take that in consideration.

The interesting bit of that class is the Current property that gets the current UnitOfWork:

    1 

    2 public static IUnitOfWork Current

    3 {

    4     get

    5     {

    6         IUnitOfWork unitOfWork = GetUnitOfWork();

    7         if (unitOfWork == null)

    8         {

    9             _unitOfWorkFactory = ObjectFactory.

   10                         GetInstance<IUnitOfWorkFactory>();

   11             unitOfWork = _unitOfWorkFactory.Create();

   12             SaveUnitOfWork(unitOfWork);

   13         }

   14         return unitOfWork;

   15     }

   16 }

   17 

We are going to look at the two methods that do the work in a moment, but first of all notice that we have a UnitOfWorkFactory to produce our specific UnitOfWork. Furthermore we are going to use the StructureMap Service Locator to get our dependency on a concrete factory.

Either in configuration or in code we need to set up which concrete type the requested type should resolve to like so. In code it would be something like this:

    2 

    3 ObjectFactory.Initialize(

    4     x =>

    5     {

    6         x.ForRequestedType<IUnitOfWorkFactory>().

    7             TheDefaultIsConcreteType<EFUnitOfWorkFactory>();

    8 

    9         x.ForRequestedType(typeof(IRepository<>)).

   10             TheDefaultIsConcreteType(typeof(EFRepository<>));

   11     }

   12 );

   13 

We map it to the concrete factory implementation for our Entity Framework project. The IRepository<T> is also mapped to the concrete type EFRepository that we created earlier.

The EFUnitOfWork factory has the responsibility of creating new units of work, implements the IUnitOfWorkFactory and has a method that takes a delegate which, when called creates an instance of the ObjectContext we want to work on.

    1 

    2 public class EFUnitOfWorkFactory : IUnitOfWorkFactory

    3 {

    4     private static Func<ObjectContext> _objectContextDelegate;

    5     private static readonly Object _lockObject = new object();

    6 

    7     public static void SetObjectContext

    8         (Func<ObjectContext> objectContextDelegate)

    9     {

   10         _objectContextDelegate = objectContextDelegate;

   11     }

   12 

   13     public IUnitOfWork Create()

   14     {

   15         lock (_lockObject)

   16         {

   17             ObjectContext context = _objectContextDelegate();

   18         }

   19         return new EFUnitOfWork(context);

   20     }

   21 }

   22 

UnitOfWork/ObjectContext lifespan

So back to the UnitOfWork. As mentioned the ObjectContext is not threadsafe, so we need to make sure that when re-using the objectcontext we dont run into issues with that.

If we are in a web-application we probably want to at least scope the context to maximum the lenght of the request. If we tied it to a static class member, it would share lifespan with the AppDomain and that is bound to cause problems.

Maybe it would make sense to work in smaller cohesive chunks of one or few business transactions and you could create a UnitOfWork scope to handle that, but for the sake of the example we are going to tie it to HttpContext.Current.Items and thereby limit the lifespan to the current request.

When we are not in a web application we need to handle multithreaded scenarios at least, and it would probably make most sense to have a scope of a business transaction, but in this context ill just handle the threading issue. This leaves us with the following methods on UnitOfWork where _threads is a Hashtable:

    1 

    2 private static IUnitOfWork GetUnitOfWork()

    3 {

    4     if (HttpContext.Current != null)

    5     {

    6         if (HttpContext.Current.Items.

    7                     Contains(HTTPCONTEXTKEY))

    8         {

    9             return (IUnitOfWork)HttpContext.Current.

   10                                     Items[HTTPCONTEXTKEY];

   11         }

   12         return null;

   13     }

   14     else

   15     {

   16         Thread thread = Thread.CurrentThread;

   17         if (string.IsNullOrEmpty(thread.Name))

   18         {

   19             thread.Name = Guid.NewGuid().ToString();

   20             return null;

   21         }

   22         else

   23         {

   24             lock (_threads.SyncRoot)

   25             {

   26                 return (IUnitOfWork)_threads

   27                     [Thread.CurrentThread.Name];

   28             }

   29         }

   30     }

   31 }

   32 

   33 private static void SaveUnitOfWork(IUnitOfWork unitOfWork)

   34 {

   35     if (HttpContext.Current != null)

   36     {

   37         HttpContext.Current.Items

   38                     [HTTPCONTEXTKEY] = unitOfWork;

   39     }

   40     else

   41     {

   42         lock(_threads.SyncRoot)

   43         {

   44             _threads[Thread.CurrentThread.Name] = unitOfWork;

   45         }

   46     }

   47 }

   48 

Conclusion

So we end up being able to write the following code:

    5 IRepository<Order> orderRep = ObjectFactory.

    6     GetInstance<IRepository<Order>>();

    7 IRepository<Customer> custRep = ObjectFactory.

    8     GetInstance<IRepository<Customer>>();

    9 

   10 Order o = new Order();

   11 o.CreatedDate = DateTime.Now;

   12 o.Status = 100;

   13 o.Customer = custRep.First(x => x.Id == 1);

   14 orderRep.Add(o);

We are programming against the interfaces and we use our POCO classes. We hook up our concrete DB dependend implementations with the StructureMap Service Locator, and we have control over the scope and lifespan with our UnitOfWork implementation.

But have a look at the code. Be advised though - it is not production ready code – it needs tests, guards and errorhandling, and it serves only as a sort of Proof of concept for EF4.