Entity Framework – Some common hurdles

17 בנובמבר 2008

I just read a post “Entity Framework – Disappointment” where a decision was made to ditch the EF because of some deficiencies. I want to emphasize that I know nothing about that specific project and the point of this post is not by any means to “attack” their approach. It is not my intention to pick on that specific post since I’ve seen similar complaints elsewhere. It did catch my attention though. I started with a comment, but it quickly became too long.
My first reaction when I read the list was that I wanted to check how difficult it would be to deal with these issues in our repository implementation.


The list of deficiencies:



  1. No eager loading. Need to specify .Include(“”) for every query.

  2. No way to make to turn change tracking on/off except from changing every query.

  3. A bug that prevents simple queries where nvarchar columns are used in the criteria.

  4. A designer error with a cryptic error message.

Before I go over the list of issues, it is important to note that in our whole system which has many hundred queries there is only one ObjectQuery<T>. What makes each query return different data are the specifications passed to the GetXXX() methods.


Every query in the repository is created by a method that looks similar to the following. The real implementation is a little bit more complex than this.



/// <summary>


/// Create a query for type T.


/// </summary>


private ObjectQuery<T> CreateQuery<T>()


{


    ObjectQuery<T> query;


    string entitySetName = GetEntitySetName(typeof(T));


    query = ObjectContext.CreateQuery<T>(entitySetName);


    return query;


}



No Eager Loading


This is an issue that has been criticized a lot since the initial release of the Entity Framework. Since I didn’t know how to achieve this, I’ll walk us through the exploratory steps towards a somewhat simplistic solution.


The eager loading requirements I defined were as following.



  • A property on the repository should allow the developer consuming the repository to opt in/out for eager loading for all subsequent queries.

  • No additional parameters should be required. (No use of the IncludeBuilder mentioned in my previous post on the repository)

  • The eager load will only load related entities one level deep.

As you might know, the Entity Framework ObjectContext contains metadata. I was convinced that by exploring the metadata I would find a way to extract a list of related entities based on the type requested from the repository. After spending a few minutes in the debugger looking at a loaded ObjectContext I found that the MetaDataWorkspace contains all the information we need. Now we only need to write the code…


Here’s the method that retrieves the navigation values that we will need to insert into the calls to .Include(“”).



private IEnumerable<string> GetEntitySetNavigations(EntitySet entitySet)


{


    return entitySet.ElementType.NavigationProperties.Select(p => p.Name);


}


We can now change the CreateQuery() to include the following.



if (EagerLoad)


{


    foreach (string navigation in GetEntitySetNavigations(entitySet)


    {


        query = query.Include(navigation);


    }


}


return query;


That’s it. Eager loading by setting a property on the repository.


No property to turn change tracking off


Since the property that determines change tracking is a property of the ObjectQuery<T>() variable in CreateQuery, we can solve the tracking issue by adding a property to the repository as well.


public bool TrackChanges { get; set; }


We now need to check this property in the CreateQuery() method.


We’ll change the last line of CreateQuery() to:




if (!TrackChanges)


    query.MergeOption = MergeOption.NoTracking;


return query;



This effectively allow us to turn change tracking on and off as we see fit either on a per query or per session basis.


Can’t use nvarchar in criteria


We have not encountered this issue. I read the msdn forum thread referenced and I agree that this could be a showstopper.


Cryptic error messages by the designer.


I agree. The designer is not very helpful in telling you where things went wrong. In order to make things a little smoother, I usually add a few entities at a time. That way you narrow down where your issues are. Not that that makes dealing with the errors much fun, but I haven’t gotten hung up too much.


To summarize, the Entity Framework has a lot of power, and it does take some time to get familiar with it. But I guess that’s the case for any complex technology. I would have to disagree with the blanket statement that EF is a disappointment. It does have some rough edges, but that’s the case with many v1 technologies. If you don’t mind doing some plumbing code then EF can be a good choice IMHO.


BTW, It took much longer to write this post than to code changes to the repository. Maybe I should stick with coding. :-)

kick it on DotNetKicks.com

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

6 comments

  1. Ariel Ben Horesh18 בנובמבר 2008 ב 10:03

    I've got a feeling that EF is half baked or not v1 at the least.

    Maybe SQL CE is bringing the worst from it.

    BTW – although it is ambiguous from the title, the biggest disappointment was my own :) .

    Reply
  2. FransBouma20 בנובמבר 2008 ב 4:00

    "That’s it. Eager loading by setting a property on the repository."
    that's not eager loading, that's simply fetching the whole graph or at least much more data than you probably want. It also isn't flexible.

    If you want to know what eager loading should look like and how linq constructs can help, see:
    http://weblogs.asp.net/fbouma/archive/2008/07/03/linq-to-llblgen-pro-feature-highlights-part-2.aspx
    (see the part: "Hierarchical fetching of entity graphs using Prefetch Paths"). So if I want to fetch all customers from Israel with their last 10 orders sorted by order date, I should be able to do so.

    Reply
  3. Kim20 בנובמבר 2008 ב 4:38

    @Frans,
    Thank you for your comment. I have read enough of your writings to have great respect for your opinions!
    I read your post, and stand corrected and agree on all points.

    Kim

    Reply
  4. liviu20 בנובמבר 2008 ב 5:05

    It is a shame that one has to write its own implementation of a repository.
    You say that you developed this layer rapidly, so
    one would expect that a product of EF complexity would offer the same kind of flexible repository pattern by default.

    Giving the static api exposed, one would think that the people responsible with the public api of the product are mediocre programmers that never wrote a db application in their lives, except one targeting Northwind.

    Reply
  5. Kim20 בנובמבר 2008 ב 5:41

    @Liviu,
    Writing the repository did not take long at all. It did take some time to learn EF though. For example , the rather stupid implementation of the "over eager" loading took only 10 minutes to add. The change tracking was just a property and an if() check. The problem IMHO, is that it is difficult to please everyone when you write a commercial application. For our repository, we just add/change where and when we need to. Frans commented that it wasn't flexible, and I don't have to be. I just have to fulfill the requirements of our project.

    Kim

    Reply
  6. ToratordDrale25 בפברואר 2011 ב 21:41

    CrazyLiam123|LOL At the random Tomatoes. XD I couldnt see it all tho coz of frickin Loadingп»ї -.-
    http://genericsmeds.com/?p=123

    thplousaqq

    Reply