Entity Framework Tips and Tricks: Use GetObjectByKey When Querying a Single Entity

Sep 7, 2011  • C#

I’ve been using Entity Framework a lot lately and it makes data access really nice. It’s fairly simple to use and maps all your tables to a .NET object model. However, just like any other library, it can be misused and have it’s own issues. I’ve been figuring some things out as I’ve been using it, so I thought I’d share a few tip and tricks that I’ve learned. Here’s the first one:

Use “GetObjectByKey” when Querying for a Single data entity

Take the following query:

var person = (from p in context.Persons
where p.ID == id
select p).FirstOrDefault();

This query will find all the Person entities that have a specific ID and then return the first one or null if it doesn’t exist. This query is perfectly valid and will operate as expected. However, if you were to call that query multiple times, it will hit the database every time it’s called and never cache the entity. In order to “cache” the entity for future calls you would need to keep the person variable around for any future use.

Now, take the following code:

var keyValues = new KeyValuePair<string, object>[] {
new KeyValuePair<string, object>("ID", id)
};
var key = new EntityKey("DataEntities.Persons", keyValues);

var person = (Person)context.GetObjectByKey(key);

This code uses the GetObjectByKey method to return the same Person entity as the above query. However, there is one critical difference. This code will check the cache before hitting the database to see if the entity has already been loaded into memory using Entity Framework.

Basically, the first call to GetObjectByKey will query the database, and any subsequent calls for the same entity will just return it from the cache. You must remember when using this method that it wont refresh the data from the database if it exists in the cache, so in certain circumstances, it may still be better to perform a query to make sure the data returned is the latest and not stale.

The GetObjectByKey method will throw an ObjectNotFoundException if the requested object cannot be found. To avoid handling the exception, you can alternatively use the TryGetObjectByKey method instead.

Here’s a generic method and it’s sample usage that I’ve created to make using TryGetObjectKey a little simpler:

static T GetEntityByID<T>(string entitySetName, Guid id)
where T: class
{
    object val = null;
    // Create the EntityKey
    var keyValues = new KeyValuePair<string, object>[] {
        new KeyValuePair<string, object>("ID", id)
    };
    var key = new EntityKey(
        string.Format("DataEntities.{0}", entitySetName),
        keyValues
    );
    
    // Try to get the Object using the Key
    context.TryGetObjectByKey(key, out val);
    
    // cast the object as T
    // this will return Null if the object doesn't exist
    return val as T;
}

// Example usage of the method
var person = GetEntityByID<Person>("Persons", id);

You could even go a step further and wrap the above GetEntityByID<Person>() call into a method like GetPersonByID(Guid id) to make it easier to use.