Jor*_*rin 15 asp.net-mvc entity-framework
我的EF上下文之间Issues
和之间存在多对多的关系Scopes
.在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);
}
}
Run Code Online (Sandbox Code Playgroud)
所以,当我尝试添加逻辑来保存相关的范围时,我尝试了几件事,但最终,这对我来说最有意义:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
但是,不幸的是,这只会引发以下异常:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
Ale*_*mes 12
存根通常仅对1-*
关系有效.
*-*
关系引入了一系列不同的挑战.
也就是说,当你附加两端时 - 不像1-*
- 你仍然不知道这种关系是否已经存在.
这意味着这段代码:
if (issue.Scopes.Contains(thisScope))
Run Code Online (Sandbox Code Playgroud)
每次都可能会返回假.
我会做的是:
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.
Run Code Online (Sandbox Code Playgroud)
现在,您需要找出需要添加和删除issue.Scopes的内容.您可以通过基于ID进行比较来完成此操作.
即如果您有一组范围ID,您希望与该问题相关(relatedScopes)
然后,此代码将确定要添加的内容和要删除的内容.
int[] toAdd = relatedScopes.Except(issue.Scopes.Select(s => s.ID)).ToArray();
int[] toRemove = issue.Scopes.Select(s => s.ID).Except(relatedScopes).ToArray();
Run Code Online (Sandbox Code Playgroud)
现在为了添加你这样做:
foreach(int id in toAdd)
{
var scope = new Scope{Id = id};
edmx.Scopes.Attach(scope);
issue.Scopes.Add(scope);
}
Run Code Online (Sandbox Code Playgroud)
对于您需要删除的每个范围
foreach(int id in toRemove)
{
issue.Scopes.Remove(issue.Scopes.Single(s => s.ID == id));
}
Run Code Online (Sandbox Code Playgroud)
到现在为止,应该形成正确的关系.
希望这可以帮助
微软
归档时间: |
|
查看次数: |
4659 次 |
最近记录: |