以下是我的结论,效果非常好:
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已经可以为我们这样做了!).
Edit, twelve years later (Dec 2021)... oof!
以下是我在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 });
你可以重构它来使用实体键,但这已经足够让任何人都go 做了!