Is is possible to check if an object is already attached to a data context in Entity Framework?
Here's what I ended up with, which works very nicely:
public static void AttachToOrGet<T>(this ObjectContext context, string entitySetName, ref T entity)
where T : IEntityWithKey
{
ObjectStateEntry entry;
// Track whether we need to perform an attach
bool attach = false;
if (
context.ObjectStateManager.TryGetObjectStateEntry
(
context.CreateEntityKey(entitySetName, entity),
out entry
)
)
{
// Re-attach if necessary
attach = entry.State == EntityState.Detached;
// Get the discovered entity to the ref
entity = (T)entry.Entity;
}
else
{
// Attach for the first time
attach = true;
}
if (attach)
context.AttachTo(entitySetName, entity);
}
You can call it as follows:
User user = new User() { Id = 1 };
II.AttachToOrGet<Users>("Users", ref user);
This works very nicely because it's just like context.AttachTo(...)
except you can use the ID trick I cited above each time. You end up with either the object previously attached or your own object being attached. Calling CreateEntityKey
on the context makes sure it's nice and generic and will work even with composite keys with no further coding (because EF can already do that for us!).
A simpler approach is:
bool isDetached = context.Entry(user).State == EntityState.Detached;
if (isDetached)
context.Users.Attach(user);
Try this extension method (this is untested and off-the-cuff):
public static bool IsAttachedTo(this ObjectContext context, object entity) {
if(entity == null) {
throw new ArgumentNullException("entity");
}
ObjectStateEntry entry;
if(context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry)) {
return (entry.State != EntityState.Detached);
}
return false;
}
Given the situation that you describe in your edit, you might need to use the following overload that accepts an EntityKey
instead of an object:
public static bool IsAttachedTo(this ObjectContext, EntityKey key) {
if(key == null) {
throw new ArgumentNullException("key");
}
ObjectStateEntry entry;
if(context.ObjectStateManager.TryGetObjectStateEntry(key, out entry)) {
return (entry.State != EntityState.Detached);
}
return false;
}
To build an EntityKey
in your situation, use the following as a guideline:
EntityKey key = new EntityKey("MyEntities.User", "Id", 1);
You can get the EntityKey
from an existing instance of User
by using the property User.EntityKey
(from interface IEntityWithKey
).