asp.net-mvc – 实体框架更新实体以及子实体(必要时添加/更新)

我的EF上下文中的问题和范围之间存在多对多的关系.在ASP.NET MVC中,我提出一个允许用户编辑特定问题的编辑表单.在表单的底部,是一个允许他们选择适用于此问题的范围的复选框列表.编辑问题时,可能会始终有一些与之相关联的范围 – 这些框将被检查.但是,用户有机会检查更多的范围或删除当前检查的一些范围.我的代码看起来像这样只能保存问题:
using (var edmx = new MayflyEntities())
            {
                Issue issue = new Issue { IssueID = id,TSColumn = formIssue.TSColumn };
                edmx.Issues.Attach(issue);

                UpdateModel(issue);

                if (ModelState.IsValid)
                {
                    //if (edmx.SaveChanges() != 1) throw new Exception("UnkNown error. Please try again.");
                    edmx.SaveChanges();
                    TempData["message"] = string.Format("Issue #{0} successfully modified.",id);
                }
            }

所以,当我尝试添加逻辑来保存关联的范围时,我尝试了几件事情,但最终,这对我来说是最有意义的:

using (var edmx = new MayflyEntities())
            {
                Issue issue = new Issue { IssueID = id,TSColumn = formIssue.TSColumn };
                edmx.Issues.Attach(issue);

                UpdateModel(issue);

                foreach (int scopeID in formIssue.ScopeIDs)
                {
                    var thisScope = new Scope { ID = scopeID };
                    edmx.Scopes.Attach(thisScope);
                    thisScope.ProjectID = formIssue.ProjectID;
                    if (issue.Scopes.Contains(thisScope))
                    {
                        issue.Scopes.Attach(thisScope); //the scope already exists
                    }
                    else
                    {
                        issue.Scopes.Add(thisScope); // the scope needs to be added
                    }
                }

                if (ModelState.IsValid)
                {
                    //if (edmx.SaveChanges() != 1) throw new Exception("UnkNown error. Please try again.");
                    edmx.SaveChanges();
                    TempData["message"] = string.Format("Issue #{0} successfully modified.",id);
                }
            }

但是,不幸的是,只是抛出了以下异常:

An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.

我究竟做错了什么?

解决方法

存根通常仅对1- *关系有效.
* – *关系引入了一系列不同的挑战.

也就是说,当你连接两端 – 不像1- * – 你仍然不知道关系是否已经存在.

所以这意味着这段代码

if (issue.Scopes.Contains(thisScope))

每次都可能会返回错误.

我会做的是这样的:

edmx.Issues.Attach(issue);
UpdateModel(issue);
// or ctx.LoadProperty(issue,"Scopes") if it is a POCO class.
issue.Scopes.Load(); // hit the database to load the current state.

现在你需要找出你需要添加的从问题中删除.
您可以通过基于ID的比较来做到这一点.

即如果您有一组要与问题相关的范围ID(relevantScopes)

然后这个代码解决了要添加内容以及要删除内容.

int[] toAdd = relatedScopes.Except(issue.Scopes.Select(s => s.ID)).ToArray();
int[] toRemove = issue.Scopes.Select(s => s.ID).Except(relatedScopes).ToArray();

现在要添加你这样做:

foreach(int id in toAdd)
{
   var scope = new Scope{Id = id};
   edmx.Scopes.Attach(scope);
   issue.Scopes.Add(scope);
}

对于每个范围,您需要删除

foreach(int id in toRemove)
{
   issue.Scopes.Remove(issue.Scopes.Single(s => s.ID == id));
}

现在应该形成正确的关系.

希望这可以帮助

Alex

微软

相关文章

### 创建一个gRPC服务项目(grpc服务端)和一个 webapi项目(...
一、SiganlR 使用的协议类型 1.websocket即时通讯协议 2.Ser...
.Net 6 WebApi 项目 在Linux系统上 打包成Docker镜像,发布为...
一、 PD简介PowerDesigner 是一个集所有现代建模技术于一身的...
一、存储过程 存储过程就像数据库中运行的方法(函数) 优点:...
一、Ueditor的下载 1、百度编辑器下载地址:http://ueditor....