Querying the entity set directly always queries the database. Querying Local
(or the ObjectContext
equivalent) always queries the entities in memory. But what if you want to do both? If an entity has been loaded, you want to work with the version in memory. If it hasn’t been loaded, you want to load it. Seems perfectly reasonable to me. Again, both the DbContext
and ObjectContext
APIs provide a means to do this, and the DbContext
version is a bit easier to use. But this time the difference isn’t quite so striking.
With the the DbSet<T>.Find()
method, the only (possibly) tricky bit is knowing the primary key of the entity you want.
The DbSet<T>.Find()
method will only make a trip to the database if it can’t find the primary key you’re looking for. If the entity is in already in memory, that’s what it will return. (And if it can’t find it at all, it will return a null
, which eliminates some tedious error handling code.)
Recipe theRecipe = context.Recipes.Find(3);
If your entity has a composite primary key, you just provide the values in the order they’re defined. (Remember the Ordinal
annotation/Fluent API method?)
Supplier theSupplier = context.Suppliers.Find("Joe", "Smith");
The ObjectContext
version of DbSet<T>.Find()
is GetObjectByKey()
. It’s functionally very similar to DbSet<T>.Find():
It only makes a trip to the database if the entity isn’t in memory. But there are two important differences: You must construct an EntityKey
to use as the argument to the method, and if the specified key isn’t found, the method throws an ObjectNotFoundException
rather than quietly returning null
. (There’s also a TryGetObjectByKey()
method, but the syntax is so ghastly that I frankly don’t think it’s worth the bother. You can check MSDN if you’re feeling masochistic...)
The EntityKey
constructor has several overloads, but you’ll probably use the one that takes the entity set (qualified with its container), the key property, and the value most often:
EntityKey myKey = new EntityKey("RecipeEntites.Recipes",
"RecipeId", 3);
Once you have an instance of the EntityKey
, you can use the GetObjectByKey()
method wrapped in a Try...Catch
statement:
try
{ Recipe theRecipe = context.GetObjectByKey(myKey); }
catch (ObjectNotFoundException ex)
{ console.Writeline(ex.ToString()); }
Try
theRecipe As Recipe = context.GetObjectByKey(myKey)
Catch (ex As ObjectNotFoundException)
console.Writeline(ex.ToString())