我正在尝试找到更新多对多关系的合适形式,但是我发现了一些问题。
该应用程序是带有简单注入器的asp.net mvc(根据上下文设置)
我有一个具有IEnumerable的实体People,也有一个具有IEnumerable的实体Team。
人员实体还有其他字段,如描述,电子邮件等,并且在其视图中有一些复选框,因此用户可以选择团队。
我曾尝试在网上搜索更新多对多关系的最佳方法,而我发现的所有内容就是删除已创建的第三张表中的所有内容,然后再次添加团队。
下面是我正在尝试做的事情,但是我正在获取PK已经存在。我知道它在发生,因为首先我使用Find方法加载People实体(以删除foreach中的团队列表),然后尝试附加(发生错误时)将修改后的对象设置为“已修改”,即状态为“已修改”。
public override void Modify(People obj)
{
var ppl = SearchById(obj.Id);
if (ppl.Teams.Count > 0)
{
foreach (var team in ppl.Teams.ToList())
{
ppl.Teams.Remove(team);
}
}
var entry = lpcContext.Entry(obj);
if (lpcContext.Entry(obj).State == EntityState.Detached)
dbSet.Attach(obj);
entry.State = EntityState.Modified;
}
为了说明问题,我使用工作单位模式,因此稍后保存更改。
还有其他方法吗,或者我必须逐个删除Teams,然后进行SaveChanges,然后再更新对象和SaveChanges?
不幸的是,在EF中,与分离的实体一起工作并没有那么简单(到目前为止)。EF中的Attach()仅适用于连接的实体。这意味着,如果您从数据库加载对象,则将其传递到视图(或页面为asp.net)。当您从该视图/页面读回对象时,EF将不再跟踪该对象。如果现在尝试使用Attach(),则会收到错误消息,表明密钥已存在于DBContext中。要解决此问题,您需要找到条目并使用SetValues()对实体进行更改。像这样的东西:
public virtual void Update(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State == EntityState.Detached)
{
var pkey = _dbset.Create().GetType().GetProperty("Id").GetValue(entity);//assuming Id is the key column
var set = DbContext.Set<T>();
T attachedEntity = set.Find(pkey);
if (attachedEntity != null)
{
var attachedEntry = DbContext.Entry(attachedEntity);
attachedEntry.CurrentValues.SetValues(entity);
}
}
}
请注意,这将忽略任何嵌套对象。因此,您应该跳出数据库,并比较从数据库返回的对象,以了解是否应该在每个子对象上调用添加,更新或删除。这是在EF中处理断开连接的对象时可以找到的最佳解决方法。我猜nHibernate没有这个错误。最后我读到了有关此内容的信息,Microsoft将在EF 6.x之后对此进行处理。因此,我想我们将不得不等待。请仔细阅读下面的文章,以详细了解该问题(以及可能的解决方案):
要谈论您的特定场景,您应该命中数据库,并通过比较数据库返回的人员对象与返回的人员对象来比较是否选择了任何新团队或是否删除了一些现有团队,并根据需要调用添加或删除操作。从视图/页面。要更新People对象本身,可以使用上面提供的Update()。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句