DCSIMG
Entity Framework 4.1– beware of the DbSet.Find method - Ido Flatow's Blog Veni Vidi Scripsi

Ido Flatow's Blog

Veni Vidi Scripsi

News

Have you heard me speak?
Powered
<style type='text/css' media='screen' id='sm_css'> #smix {overflow: visible;height: auto;border-radius: 10px;max-width: 250px;background-color: #323232;text-align: left;font-size: 12px;line-height: 16px;font-family:'Lucida Sans Unicode','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;-webkit-border-radius: 10px;-moz-border-radius: 10px;border-radius: 10px;} #smix a {color: #0056CC;text-decoration: none;} #smix .sm_head {color: #fff; line-height: 1em;font-size: 1.4em;padding: 10px;color: #fff;} #smix .sm_lanyard_wrapper {background-color: #fff;;clear: both;width: 97%;margin: 0 auto;margin-bottom: 0px;} #smix .sm_lanyard_content {padding: 7px;}#smix button.sm_rec, #smix a.sm_rec, #smix input[type=submit].sm_rec { padding: 6px 10px; -webkit-border-radius: 2px 2px;-moz-border-radius: 2px; border-radius: 2px; border: solid 1px rgb(153, 153, 153); background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(255, 255, 255)), to(rgb(221, 221, 221))); color: #333; text-decoration: none; cursor: pointer; display: inline-block; text-align: center; text-shadow: 0px 1px 1px rgba(255,255,255,1); line-height: 1; }#smix .sm_rec:hover { background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(248, 248, 248)), to(rgb(221, 221, 221))); }#smix .sm_rec:active { background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(204, 204, 204)), to(rgb(221, 221, 221))); }#smix .sm_rec.medium { padding: 3px 7px; font-size: 13px; }#smix .sm_rec span.icon.thumbs_up {background-position: 0px 36px;vertical-align: text-top;display: inline-block;margin-right: 4px;height: 18px;width: 16px;background-image: url(http://speakermix.com/images/new/thumbsold.png);}#smix .sm_rec:hover span.icon.thumbs_up {background-position: 0px 18px;} #smix .sm_events {padding:2px 0px 4px 0px;} #smix .sm_section {font-size: 10px; border-bottom: 1px solid silver; margin-bottom: 6px;} #smix .sm_subline {font-size:120%;margin-top:4px;font-weight:bold} #smix .powered {text-align: right} #smix .powered img {margin: 7px} </style>
Sela Technology Center

Advertisement

Entity Framework 4.1– beware of the DbSet.Find method

One of the new features of Entity Framework 4.1 is the DbContext API which is basically a simplification of the ObjectContext API, and is intended to make your life a bit easier.

In this new API you can find the DbSet.Find method which according to MSDN does the following:

“Uses the primary key value to attempt to find an entity tracked by the context. If the entity is not in the context then a query will be executed and evaluated against the data in the data source, and null is returned if the entity is not found in the context or in the data source…”.

The section I underlined (“evaluated against the data in the data source”) is the one that you should beware of - the inner implementation of the Find() method creates a query that runs in the database and searches the entity set for the entity you want to find according to the ID which is passed to the method.

Now what’s wrong with the sentence I just wrote? it searches for the entity according to the ENTITY SET, not the entity type! This is a snippet from the implementation (using ILSpy):

image

image

If your model uses simple entity types, with no inheritance between them, you won’t have a problem with the Find() method, but… if your model contains an inheritance tree, and you try to use the method to find a derived type, then the method will create a query that searches the entire class hierarchy from the base type downwards – in all the child tables, instead of looking into the specific entity type’s table. This type of query will at the minimum take more time to execute because of all the joins between the tables, and in the worst case scenario – if you have many entity types mapped to different tables, it will crash because it will try to created a nested query with too many levels (check the “Query Complexity” section in the Performance Considerations for EF in MSDN).

What can you do? if you have a base type for all your entities, first ask yourself why you need the base type, since it usually creates problems with Entity Framework – there are several ways to overcome this, either by using interfaces, or by using base types not mapped to the EF model. If you do need the inheritance and do want to use the Find method’s technique of first looking in the loaded entities before searching the database, just write an extension method for the DbSet that first searches the loaded entities by looking in the DbSet.Local collection and if the entity isn’t found, run a SingleOrDefault query in the database.

kick it on DotNetKicks.com Shout it

Comments

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# August 1, 2011 2:49 PM

Ido Flatow said:

This is a comment I got on DotNetKicks and my reply to it:

Usually, we do not create complex inheritance trees while using Entity framework. The maximum depth of inheritance is usually 2. So, the case of the application crashing because of finding an entity is very remote. This is one more reason why we should avoid inheritance while using Entity framework.

Reply:

The matter is not only the depth of the tree, but also the number of derived types - when using queries on entity sets, the query will include all entity types, so it doesn't matter how deep your tree is but how many "nodes" you have in the tree.

One thing I see in models people build is that they use a "base entity" for all of their entity type, so if you have 50 entities which is not that far fetched, you would get a query spanning 50 tables, and that can easily throw an sql exception.

Usually people use base classes for common properties such as ID, version, etc..., but today with EF 4/4.1 you can implement it quite easily with interfaces, or even with base types that do not participate in the model (this is thanks to the T4 templates and code first options).

I don't think that the saying "avoid inheritance in EF" is correct - there are many situations where it is needed, one situation for instance is the need for polymorphism in collections, and is not always easy to implement using interfaces. What I am saying is that if inheritance is used, you must understand its meaning. Also, from my experience in EF, using a base entity for all the entity types is bad EF design, it will simply a lot of problems when running queries and when loading the model metadata into the memory, and should be avoided. Fortunatelly, EF 4/4.1 has easy ways to solve this using T4 and code first, as I mentioned before.

# August 2, 2011 9:56 AM

Laster said:

I don't even know how I ended up here, but I thought this post was good. I don't know who you are

but certainly you are going to a famous blogger if you aren't already ;) Cheers!

# July 23, 2012 9:02 AM

Orth said:

Wow! In the end I got a blog from where I be capable of actually take helpful

information regarding my study and knowledge.

# August 6, 2012 8:39 PM

Rushing said:

It's hard to come by experienced people about this subject, however, you sound like you know what you're talking

about! Thanks

# March 31, 2013 9:42 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: