Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架多对多更新_C#_Asp.net_Entity Framework - Fatal编程技术网

C# 实体框架多对多更新

C# 实体框架多对多更新,c#,asp.net,entity-framework,C#,Asp.net,Entity Framework,我正试图找到更新多对多关系的合适形式,但我发现了一些问题 该应用程序是一个带有简单注入器的asp.net mvc(根据上下文设置) 我有一个实体人有一个IEnumerable,我还有一个实体团队有一个IEnumerable 人员实体有一些其他字段,如描述、电子邮件等,在其视图中,有一些复选框,用户可以选择团队 我曾试图在网上搜索更新多对多关系的最佳方法,但我只找到了删除第三个表中创建的所有内容,然后再次添加团队 下面是我试图做的,但我得到的pk已经存在。我知道这是因为首先我用Find方法加载Pe

我正试图找到更新多对多关系的合适形式,但我发现了一些问题

该应用程序是一个带有简单注入器的asp.net mvc(根据上下文设置)

我有一个实体人有一个IEnumerable,我还有一个实体团队有一个IEnumerable

人员实体有一些其他字段,如描述、电子邮件等,在其视图中,有一些复选框,用户可以选择团队

我曾试图在网上搜索更新多对多关系的最佳方法,但我只找到了删除第三个表中创建的所有内容,然后再次添加团队

下面是我试图做的,但我得到的pk已经存在。我知道这是因为首先我用Find方法加载People实体(删除foreach中的团队列表),然后尝试附加(当错误发生时)修改的对象以将其状态设置为modified

        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;
    }
为了解决一些问题,我使用了工作单元模式,所以我会在以后保存更改


是否有其他方法,或者我必须逐个删除团队,保存更改,然后再次更新对象并保存更改?

不幸的是,在EF中使用分离的实体并不是那么简单(目前)。EF中的Attach()仅适用于连接的实体。这意味着,如果从DB加载对象,则将其传递到视图(或者页面是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);
                }                    
            }                
        }
公共虚拟无效更新(T实体)
{
DbEntityEntry DbEntityEntry=DbContext.Entry(实体);
if(dbEntityEntry.State==EntityState.Distached)
{
var pkey=_dbset.Create().GetType().GetProperty(“Id”).GetValue(entity);//假设Id是键列
var set=DbContext.set();
T attachedEntity=set.Find(pkey);
如果(附件身份!=null)
{
var attachedEntry=DbContext.Entry(attachedEntity);
attachedEntry.CurrentValues.SetValues(实体);
}                    
}                
}
请注意,这将忽略任何嵌套对象。因此,您应该执行DB trip,并比较从DB返回的对象,以确定是否应该对每个子对象调用Add、Update或Delete。这是我在EF中处理断开连接的对象时能找到的最佳解决方法。我想nHibernate没有这个bug。上次我读到这篇文章时,微软打算在EF6.x之后再做这方面的工作。所以,我想我们得等着。请通读以下文章,以详细了解问题(以及可能的解决方案):


要讨论您的特定场景,您应该点击DB,查看是否选择了任何新团队或删除了某些现有团队,并通过比较DB返回的人员对象的团队集合与从视图/页面返回的人员对象来调用add或delete(视情况而定)。要更新People对象本身,可以使用上面给出的update()。

是否加载了相同的上下文?@Rob是的Rob,我忘了说,我正在使用MVC和Simple Injector(每个请求的上下文)。我将编辑问题这是一个很好的解决方法,我必须尝试一下,因为我找不到关于这个问题的任何其他信息。谢谢你!