Tip 24 – How to get the ObjectContext from an Entity

Customers often ask how to get from an Entity back to the ObjectContext .

Now generally we don’t recommend trying this. But sometimes you really need a way to get to the ObjectContext.

For example if you are in method and all you have is the Entity, and you need the ObjectContext perhaps to do some extra queries etc.

One option is to change the method signature so callers have to pass in the ObjectContext whenever this method is called. Unfortunately changing the signature like that is not always possible, especially if you are implementing some persistent ignorant interface, a Repository for example or  if doing so causes cascading changes all over your code base, yuck.

Another option is to put the ObjectContext in a thread local variable. Similar to the way HttpContext.Current works.

But both of these solutions might not be available to you…

Caveats:

Before I get to the solution a couple of important Caveats are in order:

Caveat #1: This solution only works if the Entity has at least one relationship.

Caveat #2: This solution won’t demonstrate ideal performance characteristics, because although we are just getting the Context, it calls a number of intermediary methods that involve some lookups / calculations:

Caveat #3: This won’t work with Detached entities. Although surprisingly it does work with NoTracking queries, you might have thought that NoTracking entities are essentially Detached, but that is not strictly true. Even though NoTracking queries aren’t tracked, relationship loading still works for then, and that is what we use.

Caveats CHECK…

You’ve been warned!

Workaround:

The solution relies on a single extension method:

public static ObjectContext GetContext(
this IEntityWithRelationships entity
)
{
if (entity == null)
       throw new ArgumentNullException("entity");

var relationshipManager = entity.RelationshipManager;

var relatedEnd = relationshipManager.GetAllRelatedEnds()
.FirstOrDefault();

if (relatedEnd == null)
throw new Exception("No relationships found");

var query = relatedEnd.CreateSourceQuery() as ObjectQuery;

if (query == null)
throw new Exception("The Entity is Detached");

return query.Context;
}

How does it work?

Well in .NET 3.5 all entities with relationships implement IEntityWithRelationships, in fact even in EF4 if you have a ChangeTracking Proxy for a POCO Entity the proxy implements IEntityWithRelationships too.

From there you can access the RelationshipManager and get the first RelatedEnd, it doesn’t matter which end we choose, because we don’t care about the actual end, it is just a means to an end.

From the RelatedEnd you create, but not execute, an ObjectQuery to load the related Entity(s). If you get null it is because the Entity is detached from the ObjectContext and as I said in the Caveats you are out of luck.

Finally from the query you can get the ObjectContext.

With this extension in place you simply do this:

ObjectContext context = myEntity.GetContext();

You probably want your strongly typed Context… well that is no problem either:

MyContext context = myEntity.GetContext() as MyContext;

Easy Peasy Lemon Squeazy.

This is 24th post in my ongoing series of Entity Framework Tips.