这是我最终得到的结果,效果非常好:
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;
}
}
Usage:
var item = db.AttachToOrGet(_ => _.Id == someId, () => new MyItem { Id = someId });
您可以重构它以使用实体密钥,但这足以让任何人开始!