这是我最终得到的,效果很好:
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);
}
你可以这样称呼它:
User user = new User() { Id = 1 };
II.AttachToOrGet<Users>("Users", ref user);
这非常好用,因为它就像context.AttachTo(...) 一样,只是你每次都可以使用我上面引用的 ID 技巧。您最终会得到先前附加的对象或附加的您自己的对象。在上下文中调用 CreateEntityKey 可确保它很好且通用,并且即使使用复合键也无需进一步编码(因为 EF 已经可以为我们做到这一点!)。
编辑,十二年后(2021 年 12 月)...哎呀!
这是我在 EF Core 中使用的:
public static class EfExtensions
{
public static T AttachToOrGet<T>(this DbContext context, Func<T,bool> predicate, Func<T> factory)
where T : class, new()
{
var match = context.Set<T>().Local.FirstOrDefault(predicate);
if (match == null)
{
match = factory();
context.Attach(match);
}
return match;
}
}
用法:
var item = db.AttachToOrGet(_ => _.Id == someId, () => new MyItem { Id = someId });
您可以重构它以使用实体键,但这足以让任何人开始!