Microsoft's Entity Framework 4 Epic Fail: Part II

In this post I’ll expand on the first major reason that the Entity Framework version 4 is still inadequate for enterprise-grade use.

We as architects & software developers need to build software that works today.

If you’re doing new development with Visual Studio 2010 Beta 2 / .NET 4.0 for a system to be released after the RTM date (March 22nd 2010), you might think that the Entity Framework v4 would be a great candidate for your ORM layer.  It’s part of the .NET Framework so there’s little, if any political or (initial) financial cost to using it within an organization.  In my experience as a consultant, introducing enterprise customers to ORM (the concept), and making them comfortable with a 3rd party ORM solution takes a significant effort. 

Unfortunately there are major shortcomings to the Entity Framework 4 that still make it risky to select it as your ORM solution.  The designer for EF is still far from being reliable.  In my own personal project (in a quest to learn more about EF4), I’ve found it to lose entities (inexplicably will not import tables into the model) causing me to have to delete the model and recreate it from scratch.  This leads me to not changing the names of the association/foreign-key properties because I would lose those name changes when I update the schema & recreate the EF4 model, so we have ‘ugly’ names for association/foreign-key properties such as Foo.Bar1 Foo.Bar2.  I have also seen it fail to make necessary changes to its model after a schema update.  In one instance I made a foreign-key column nullable, updated the Entity Framework model and yet when trying to persist I still received an error about the required foreign key mapping.  After a bit of digging I found the multiplicity of the foreign-key/association was still set to “One” instead of “Zero to One”.  If they still can’t get these simple “kinks” worked out, how confident can we be with the code that is ultimately responsible for saving & retrieving our company’s most important information on a daily basis?

Against my own opinion, my current client is planning to use EF4 for a global enterprise application with several thousand users.  I believe we’ll eventually hit one or more brick walls and go back to the solution we chose at the project’s inception. 

For my personal EF4 “learning” project, I’m using SQL CE 3.5 because the application is meant for single users.  Having spent most of the last several weeks working on the UI (WPF/MVVM), I had created most of the data by hand via SQL Scripts.  All of my EF interactions to date (until yesterday) had been reading data – never thinking there would be significant problems writing data.  The first problem was Foreign Keys – how could I set a foreign key without having the foreign entity?  Typically, most ORMs provide the foreign key field so you can set it directly i.e.:

   1: orderLineItem.OrderId = 12345;

   2: orderLineItem.StatusId = 67890;

With EF4 you have the following two options:

1.  Query the database for the foreign key entity and attach it to the associated entity like so:

   1: var orderLine = DB.Models.OrderLine.CreateOrder( apple );

   2: orderLine.OrderReference.Attach(

   3:                                 (from o in db.Order where o.Id == 12345 

   4:                                  select o).First());

   5: orderLine.StatusReference.Attach( ( from s in db.OrderStatus where s.Id == 67890 

   6:                                  select s ).First());

   7: db.SaveChanges();

The major shortcoming of the above code is we are forced into querying the database for information we already have, just to play by the EF’s rules.  This is an unacceptable approach.

2.  Use the “Reference” concept:

   1: orderLine.OrderReference = new System.Data.Objects.DataClasses.EntityReference(); 

   2: orderLine.OrderReference.EntityKey = new EntityKey(“Entities.Orders”, “Id”, 12345);

The primary issues for the above code are:

  1. Magic strings that is used to specify the entity (Entities.Orders) and the “Id” field.  Compile-time checks are critical for me.  Any chance there is to eliminate common human error, it should be done.  Moreover, magic strings make refactoring using built-in Visual Studio tools (as well as with 3rd party tools like Resharper, CodeRush, etc.) much more difficult.
  2. Setting a foreign key should be a very trivial operation.  This “Reference” option is neither intuitive, nor significantly better in any way than simply applying a setter for the foreign key field.

Both of these options are overly complex and too verbose.  Is this how other popular ORMs (nHibernate, LLBLGen, etc.) do it?  Not even close.  I’ll dig deeper into this theme later in major reason #3 (We Can’t wait for Microsoft to build the features we want, when there are other inexpensive or free solutions already out there.)

The Dealbreaker

The straw that finally broke the camel’s back was when I was ready to call SaveChanges() and have my entity persist to the SQLCE 3.5 database.  I was perplexed to find out why my application blew up, the underlying EF exception read:

System.NotSupportedException: Server-generated keys and server-generated values are not supported by SQL Server Compact.

I thought to myself, I’m not doing anything out of the ordinary – my tables all have integer identity primary keys.  Surely Microsoft couldn’t have neglected to make CE Identity keys work in EF4.   They certainly did, not once but twice.  People complained about this missing “feature” in EF v1 and here we are still waiting for a solution.  Had I known from the beginning this would never work (say from the designer being smart enough during the schema import/update process to warn me about it), I would have taken an alternate approach (i.e. not use EF4, or use GUIDs for keys.)   

Regardless of what Microsoft says about the EF4 being good enough and the ADO.NET Entity Data Model designer being fixed, it’s not ready for use in building tomorrow’s applications – not even close.  I should note that the Entity Framework 4 is still in beta (#2).  Having said that, I’ve not seen any indication that Microsoft is going to fix any of the issues I’ve mentioned here (or the issues I’ll be following up with in the next 2-3 posts.)

Comments

Kanye West Louis Vuitton

Do you know about Kanye West Louis Vuitton shoes? Many good feedbacks about this kind of shoes from customers, they say it's not only very comfortable but the lowest price. If you are rich interested in buying shoes and willing to make your foot feeling comfortable, please click here Kanye West Louis Vuitton or air yeezy to visit our website, you will see all kind types of shoes you deeply love.Thank you for coming!

Air Jordan

Great post. It is actually helps me a lot to study your blog. The information of your blog is exactly great, and your blog design is Simple good. It's easy to understand your meaning. Air Jordan

Response

When it comes to setting relationships using the EF, as of beta 2 of EF4, it's now possible to create FK relationships which allow you to have an FK property on the entity and just set that.

There are changes in processes to add support for server generated columns in SQL CE but it requires an update from the SQL CE team and probably won't arrive in time for VS2010's release.

- Danny

>There are changes in

>There are changes in processes to add support for server generated columns in SQL CE but it requires an update from the SQL CE team
How come LINQ-to-SQL does this since birth without any SQL CE update?

Thanks...

Danny,

If simple FK properties are possible, then why not make it obvious (or turn them on by default, or give us something in the schema import dialog?)

The EF team is making it difficult to adopt your product because it behaves unlike any well-established ORM without any obvious benefits.

Use sensible defaults. When you can't, make choosing an approach easy to find. I've already mentioned the issue I have with the lazy-loading feature in my reply to your other comment, but it bears repeating. There's implicit behavior in moving a model from EF v1 to v4 vs starting from v4. A user would have no idea there was a difference, even though their intention might be to turn Lazy Loading on or off.

I really want the Entity Framework to succeed, because it would make my life easier - I wouldn't have to push 3rd party solutions like LLBLGen Pro or nHibernate to my customers. I would hopefully (eventually) not need to teach their developers how to use it.

With respect to the SQLCE server-generated values issue...maybe you should ask Frans Bouma how he makes it work in LLBLGen Pro (this isn't a jab, but his product seems to work in this scenario and given the direction he's taking with v3.0 (becoming more of a multi-ORM designer) - he might be inclined to help you out.)

I'm compelled to be very critical of Microsoft's decisions and efforts, given their failed attempts to date in this space. I'm still trying hard to make EF v4 work in my personal project (I converted every table/reference/etc to use uniqueidentifier) just so I don't have to move to LLBLGen.

I've been looking for an ORM since 2004 that would make my life relatively easy. The closest thing I've come to that is LLBLGen. I was forced to implement a custom ORM with some pretty obtuse (completely made-up) requirements in 2006-2007 - an extremely painful experience.

I just want something that I can feel confident in - and right now between LLBLGen and EF, EF isn't even close to the level of maturity that it needs to make me feel comfortable.

Entity Designer

Hm - we haven't had reports of the entity designer "losing entities". If you would share your database schema with us, we'd be happy to see what is going on.

You can send it (and other feedback) to: noamba __at microsoft _dot com