Reddnet Scribbles

It makes me want to gouge my eyes out with a cheese grater!

ADO.NET Entity Framework: Impressive! Powerful! Useless!

Stephen M. Redd
Friday, August 22 2008

The new Microsoft Entity Framework is the latest in a long line of very impressive, yet tragic failures in Microsoft's data access strategy...

The basics of ADO.NET are great. SqlCommand, SqlConnection and their relatives for other platforms... awesome. But almost every single version of ADO.NET has failed when it comes to useful higher level abstractions. To be sure, they each demo well and they each have uses with simple applications (like those you'd be shown a demo of).

But whenever it comes to complex applications, the abstractions tend to become cumbersome, restrictive, an inflexible. The result is that most serious application end up using 3rd party frameworks or custom abstraction layers instead and under-the-hood they tend to stick to the basic ADO.NET SqlConnections and SqlCommands to do the dirty work.

In .NET 1.x it was DataSets and SqlAdapters. In .NET 2.x it was DataTables and TableAdapters. And now we have the ADO.NET Entity Framework (EF).

I had high hopes for EF. MS had clearly recognized that a radical new approach would be needed if they were to achieve a useful abstraction without having to re-invent the same wheel over and over again every few years. They had also set some pretty good goals in terms of making EF useful in support of other data stores outside the classic relational database.

Sadly, what has been delivered in the 1.x version of EF is hopelessly crippled by the deliberate lack of implicit lazy loading.

Here is an example of what this means. Assume we have two logical EF entities that map more-or-less directly to physical tables in a database. One is the Order object and the other the Customer. These entities have a navigation relationship between each other (which is analogous to the physical database's foreign key).

If you get a reference to an Order object it will have a property called Customer. This property is how you'd navigate the relationship between the entities.

So you'd expect that if you look at MyOrder.Customer you'd get back a reference to an instance of the Customer entity... But you would be fucking wrong!

The Customer property on the instance of Order may not have been fetched from the database automatically when you obtained your reference to the Order...

Instead of implicit lazy loading, EF has "Deferred Loading"... or if you prefer you can call it "Explicit Lazy Loading". The idea is that you can check to see if the Customer has been loaded for an Order, and if not then you can explicitly load it when and if you need it. But it will not automatically load the data for these properties and related entities unless you explicitly tell the framework to do so (which is unlike most ORM frameworks, LINQ to SQL, etc.).

What happens in real applications is that you never know what has and has not been loaded. So your code is chock-full of bullshit like this:

   1:  if(!someOrder.CustomerReference.IsLoaded)
   2:  {
   3:      someOrder.CustomerReference.Load();
   4:  }
   5:  string customerLastName = someOrder.Customer.LastName;

This allows you to do what you need to be doing in your code, but the price is that you HAVE to do this all over the fucking place... every time you want to access a property that traverses a relationship. You end up with more checks for data than you do data in the first place.

Even worse than that though, when you code something to use your EF model, now you now have to somehow magically "know" which properties on your entities are going to traverse a relationship and which don't.

If you know in advance that you are going need the related data later on, then when you fetch your entity you can a technique known as "Eager Loading" to tell EF to go ahead and load up the related data in advance.

This looks like this:

   1:  var x = entities.Orders.Include("Customer");

Again, this allows you to do what needs doing, but if you are making the fetched order entity available to other classes (like as a return value from a public method)... then the caller isn't going to know if you pre-loaded the relationships or not... so they'll still have to do the whole "IsLoaded" anti-tard checking shit anyway.

In his response to a nasty online petition called the "Vote of No Confidence", Tim Mallalieu defended the lack of implicit lazy loading with this statement:

"We took a fairly conservative approach in v1.0, because we wanted developers to be aware of when they were asking the framework to make a roundtrip to the database... our take on 'boundaries are explicit'."

That has to be the most depressing statement that I've ever read regarding ANY data access technology ever!

Hey guys!

The entire point of an abstraction layer is so that developers using that layer DON'T have to be aware of the damned internal workings under the abstraction layer!!!!

But most offensive to me is the overall fact that I cannot "trust" the EF model. For example... if I have a Customer entity then I have no way to know if Orders property contains an empty collection because there aren't any orders of if it is empty because the framework hasn't loaded data. Instead of being able to trust the entity model to be accurate I have to baby sit it and constantly ask "are you sure you loaded data for this already?".

Fuck that!

Then we get into the other side effect. All the mechanisms needed to do the paranoid checking-up after EF use some counter-intuitive techniques. Before I check the Customer property on an Order entity, I have to first check up with a CustomerReference property on my Order to get information about the state of the contents of the actual Customer property? Huh?

Yeah.... that's really slick there!

The eager load technique pisses me off even more!

So I can tell the EF to go ahead and load relationships... but to load them I have to use a method that takes a fucking string as an argument?!

So now I also have to be an expert on exactly what each navigation property in my EF model is specifically named... and that without strong type checking or intellisense? Sure... I can do that, but it slows me down and is just begging for a runtime bug (typoed the name or messed up the capitalization). That means I am constantly having to refer to the damned diagram all the time too which just slows me down and annoys the shit out of me at the same time!

Using EF without lazy loading is a good way to drive yourself into becoming so paranoid you'll need to remember to take your anti-psychotic meds before you even open Visual Studio!

There are a few 3rd party attempts out there to get implicit lazy loading features with the current version of EF. These are clever hacks, and I even tested out one of those. Overall, the hacks give you a much better experience than using the stock Entity Framework as is, but this is also code that will be hard to update to use any future releases of EF too, and these impose other limitations on your code too. I suppose though that if you HAD to use EF, you'd still be smart to use one of these 3rd party techniques to get the implicit lazy loading anyway.

LINQ to SQL may lack the ability to provide a true logical abstraction for your physical data model, or do fancy inheritance, or even handle some of the more unusual data mappings...  but at least you can TRUST that properties in a LINQ to SQL Entity will actually contain data that reflects what is in the real database. Plus the overall usage pattern of LINQ to SQL is much clearer and simpler.

Until EF gets built-in implicit lazy loading, screw it... I'll just use LINQ to SQL.

Stephen M. Redd
Friday, August 22 2008
Filed under: Code
Tagged as: , , ,
13 Comments

» Trackbacks & Pingbacks

  1. Pingback from .NET Entity Framework WTF!? Part One « Grbnzo Web Development

Trackback link for this post:
http://reddnet.net/trackback.ashx?id=215

» Comments

  1. Rick O'Shay avatar

    A top-notch ORM framework should have been a slam-dunk for Microsoft. As with most technology, they get to incorporate the battle-tested designs of frameworks that have been out there for decades. Moreover, they effectively have no funding limitations. Anybody else find it puzzling that Microsoft is 15 years late with a viable ORM framework, or that in 2009 they will be releasing their first MVC framework? They have to re-invent everything, badly, and apparently it's a cardinal sin for them to pay homage to the tools they are ripping off, or should I say "borrowing" from.

    Rick O'Shay — November 23, 2008 3:45 PM
  2. Tim avatar

    I too am running into the fact that using EF with real-world applications is very impossible. I can't do simple inheritance the way a framework "should" implement this. Also, removing the option of using Attributes for data-mapping? Come on! Yes, an external file is probably good to have, however, more often than not you're not simply going "Oh, there's the bug, we just mapped to the wrong field". No, it's more like testing / debugging for two days until you find you did everything completely wrong and have to update code as well as the mappings.

    I am with you, even though I also think LINQ to SQL is full of the same short commings, I can at least use my own data mapper that I created 4 years ago and I have never written any data-mapping code since then. I've been trying to use EF, LTS, and even looked at ADO.NET Data Services. They all suck! My simple mapper is years (and betas) ahead of anything they have out now. Sad...

    Tim — December 31, 2008 12:19 AM
  3. None avatar

    Interesting that under your name there lies a huge tag "Stupid"..

    None — February 5, 2009 5:13 AM
  4. Pepa avatar

    Use more polite words dude.

    Pepa — February 9, 2009 12:09 AM
  5. James avatar

    Hey dude, I feel your rage :-) Not trying to spam you but you should check out a product called "LightSpeed" from Mindscape. I'm not involved with the company but have used there product for a while now and think its pretty awesome. Its also well supported and could be a positive alternative if LinqToSql is a dying duck...

    James — February 15, 2009 4:30 PM
  6. AndrewO avatar

    Hey, Stephen!

    I'm so angry... blogs.msdn.com/.../clarifying-the- They are going to kill L2S - much better and real workable framework...

    Tim Mallalieu sucks

    AndrewO — April 21, 2009 9:07 AM
  7. wsmith avatar

    I agree is a poor solution, and as Rick O'Shay pointed out Microsoft is many many years behind doing ORM and MVC.. It's almost like a 'back to the future' experience to me.

    >They have to re-invent everything, badly....

    I wouldn't say 'everything' but you have a void point here. This EF bug is a perfect example. A pretty elegant solution to the issue was implemented by NeXT (Apple) many many years ago. When fetching from the database it would insert DBFault objects into the object graph instead of fetching the related data. In your code you never had to check if it had been loaded, but just access it as normal. If it wasn't loaded yet, the DBFault object would stop your code, load the data in place of itself, then continue on as if the data had been there all the time.

    It was a nice easy to use solution, although not entirely a new idea. It worked very much the same as virtual memory. The data we want to access may not be in memory and may be on a disk drive but we don't check to see if its loaded... the OS just tracks access and if we try to access something that isn't loaded, it loads the memory and then lets the program proceed as if it had always been in memory.

    Don't get me started on other less than optimal 'features' we have been stuck with.... I like the improvements Microsoft is making, especially with C#... right up to the point where I remember I was using similar yet more refined features 20 years ago... While I like the changes, it sure would have been nice if Microsoft had actually learned from the past... Makes me wonder if they have never even heard of the opensource language Objective-C.

    wsmith — May 5, 2009 5:53 PM
  8. mrxliu avatar

    It is a Beta version on August 22 2008,yes ?

    mrxliu — June 2, 2009 2:47 AM
  9. Stephen M. Redd avatar

    The article was written about the beta EF version, but the complaints are still valid even now. The actual code examples look a little different on the release version of EF 1.0, but the pattern and the limitations are generally the same...

    Stephen M. Redd — August 14, 2009 12:19 PM
  10. Ryan Mrachek avatar

    Linq2Sql was pretty straight forward and I used it for some projects, but EF is driving me away for sure.

    On the loading scenario, Linq2SQl was much better approach were everything in the context was loaded and you just had to scope the context to ward off bloat. BUT.. not having all your entities on one diagram makes for a poor slide so I'm guessing ms marketing won out. It's not like they use it anyway, that's what they have Infosys for and we all know the **quality** they're know for.

    I've somewhat given up and have resined to using Hybernate for .Net it's easier to go back and forth that way.

    Ryan Mrachek — September 24, 2009 5:31 PM
  11. Chris Gutierrez avatar

    This was a very helpful post! Exactly what I was looking for. I especially love the extensive use of F bombs through out! I found myself saying... "Yeah fuck that!".

    Chris Gutierrez — December 16, 2009 3:08 PM
  12. Stephen M. Redd avatar

    Hehe, thanks. I actually get quite a lot of complaints about my use of language... but I call it "an appropriate use of lingual force!"

    I use the word that convey my thought or idea in the most effective manner possible. Glad to know it is sometimes appreciated :)

    Stephen M. Redd — December 16, 2009 3:20 PM

» Leave a Comment