DbContext 的通用合并:如何检查实体是不是已附加?
Posted
技术标签:
【中文标题】DbContext 的通用合并:如何检查实体是不是已附加?【英文标题】:Generic Merge of DbContext: how to check if entity is all ready attached?DbContext 的通用合并:如何检查实体是否已附加? 【发布时间】:2015-08-15 04:08:18 【问题描述】:给定以下代码:
void MergeDbContext(DbContext aSourceDbContext, DbContext aDestinationDbContext)
var sourceEntities = aSourceDbContext.ChangeTracker.Entries().ToList();
foreach (DbEntityEntry entry in sourceEntities)
object entity = entry.Entity;
entry.State = EntityState.Detached;
// check if entity is all ready in aDestinationDbContext if not attach
bool isAttached = false;// TODO I don't know how to check if it is all ready attched.
if (!isAttached)
aDestinationDbContext.Set(entity.GetType()).Attach(entity);
我如何一般地确定一个实体是否存在于上下文中。
【问题讨论】:
***.com/questions/6018711/… 如果有关联和修改实体,这会不会很复杂?您打算保留修改吗? @jjj 每个 DBContext 只能执行 1 个异步查询,并且我想执行多个以提高性能。所以我创建了 2 个 DBcontext,在这里我试图合并结果。对于我的特定实例,这些将是只读的并且没有更改。 【参考方案1】:这是一个扩展方法,它通过以下步骤在上下文的状态管理器中查找对象:
获取类型的关键属性 获取对象的键值 检查上下文中是否有任何实体具有对象的类型和键值。public static bool IsAttached<T>(this DbContext context, T entity)
where T : class
if (entity == null) return false;
var oc = ((IObjectContextAdapter)context).ObjectContext;
var type = ObjectContext.GetObjectType(entity.GetType());
// Get key PropertyInfos
var propertyInfos = oc.MetadataWorkspace
.GetItems(DataSpace.CSpace).OfType<EntityType>()
.Where(i => i.Name == type.Name)
.SelectMany(i => i.KeyProperties)
.Join(type.GetProperties(), ep => ep.Name, pi => pi.Name, (ep,pi) => pi);
// Get key values
var keyValues = propertyInfos.Select(pi => pi.GetValue(entity)).ToArray();
// States to look for
var states = System.Data.Entity.EntityState.Added|System.Data.Entity.EntityState.Modified
|System.Data.Entity.EntityState.Unchanged|System.Data.Entity.EntityState.Deleted;
// Check if there is an entity having these key values
return oc.ObjectStateManager.GetObjectStateEntries(states)
.Select(ose => ose.Entity).OfType<T>()
.Any(t => propertyInfos.Select(i => i.GetValue(t))
.SequenceEqual(keyValues));
用法:
bool isAttached = dbContext.IsAttached(entity);
【讨论】:
keyprops 的设置出现以下异常。 “找不到 EntityType 'System.Object' 的映射和元数据信息。”我认为是因为实体属于代理类型。 bool isAttached = aDestinationDbContext.IsAttached(entity);我是怎么称呼它的......是的,我不知道实体类型,因为我试图一般地合并两个上下文 这样可以解决异常,但是总是会返回 false。在“entity.GetType().Name”上设置监视变量我得到:“Parent_D6C692F519B2A9BA4C1E11ABFBC4086C28421AD0E3114091C3BA5A9D71089899”“entity.GetType().BaseType.Name”返回“Parent” var typename = typeof(T).Name; // 确实产生 Object 的“Object”。但是鉴于我正在尝试合并两个通用 dbcontexts,我怎么知道类型? 我不能不管这个,我终于解决了。我的错误是认为代理 inherently 总是返回基类型作为它的类型。但这只是因为大多数返回代理的方法将它们 cast 到它们的基本类型。这正是这里不会发生的事情。所以我不得不重写发现关键属性的方法。以上是关于DbContext 的通用合并:如何检查实体是不是已附加?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Lazyloading,如何在处理完其 DBContext 后使用新的 DbContext 加载相关对象?
Entity Framework :Using Transaction Scope 如何检查 DbContext 是不是有事务?
如何从实体框架 DbContext 收集当前的 SQL Server 会话 ID?