问题描述
我有一个很艰难的时期更新和删除多对多的关系与EF code-第一。
我有一个非常简单的模型:
公共类问题
{
[键]
公众诠释IssueId {搞定;组; }
公众诠释号码{搞定;组; }
公共字符串名称{搞定;组; }
公众的DateTime日期{搞定;组; } 公共虚拟的ICollection<&造物主GT;创作者获得{;组; }
} 公共类造物主
{
[键]
公众诠释的CreatorID {搞定;组; }
公共字符串名字{获得;组; }
公共字符串中间名{获得;组; }
公共字符串名字{获得;组; } 公共虚拟的ICollection<&期GT;问题{搞定;组; }
} 公共类ICBD:的DbContext
{
公共DbSet<&期GT;问题{搞定;组; }
公共DbSet<&造物主GT;创作者获得{;组; }
}
我一直无法弄清楚如何更新使用EF背景下,许多一对多realtionship。在我isnert /更新动作,我有这样的code:
[HttpPost]
公众的ActionResult EditIssue(发行问题,INT [] CreatorIds)
{
如果(CreatorIds == NULL)
ModelState.AddModelError(CreatorIds,请至少指定一个创造者); 如果(ModelState.IsValid)
{
//插入或更新的问题记录(无关系)
如果(issue.IssueId == 0)
db.Issues.Add(问题);
其他
db.Entry(问题).STATE = System.Data.EntityState.Modified;
db.SaveChanges(); //删除 - 删除当前关系
如果(issue.Creators!= NULL)
{
issue.Creators =新的List<&造物主GT;();
db.Entry(问题).STATE = System.Data.EntityState.Modified;
db.SaveChanges();
} //插入 - 创作者获得了许多一对多realtionship
issue.Creators = db.Creators.Where(X => CreatorIds.Contains(x.CreatorId))了ToList();
db.Entry(问题).STATE = System.Data.EntityState.Modified;
db.SaveChanges(); 返回RedirectToAction(「指数」);
} IssueEditModel issueEdit =新IssueEditModel {
创作者= db.Creators.ToList(),
问题=的问题,
};
返回查看(issueEdit);
}
我可以插入问题
,我可以没有问题插入新的 issue.Creators
。但是,当我试图删除当前的 issue.Creators
这样我就可以再插入新的 issue.Creators
总是空所以它永远不会更新到一个空列表。我不明白这一点。 issue.Creators
中有记录,因为当code进入插入新的创造者,我得到一个错误这样的:
冲突。不能插入对象dbo.CreatorIssues重复键。
该语句已终止。说明:执行当前Web请求的执行过程中发生未处理的异常。请查看有关错误的详细信息的堆栈跟踪以及它起源于code。异常详细信息:System.Data.SqlClient.SqlException:PRIMARY KEY约束'PK__CreatorI__13D353AB03317E3D的相关规定。不能插入对象dbo.CreatorIssues重复键。
该语句已终止。源错误:
59号线:issue.Creators = db.Creators.Where(X => CreatorIds.Contains(x.CreatorId))了ToList();
60号线:db.Entry(问题).STATE = System.Data.EntityState.Modified;
线61:db.SaveChanges();
第62行:
63号线:返回RedirectToAction(「指数」);
我如何获得 issue.Creators
来准确地显示当前的关系,所以我可以将它们删除?
更新:工作控制器
[HttpPost]
公众的ActionResult EditIssue(发行问题,INT [] CreatorIds)
{
如果(CreatorIds == NULL)
ModelState.AddModelError(CreatorIds,请至少指定一个创造者); 如果(ModelState.IsValid)
{
//插入或更新的问题记录(无关系)
如果(issue.IssueId == 0)
db.Issues.Add(问题);
其他
db.Entry(问题).STATE = System.Data.EntityState.Modified;
db.SaveChanges(); // INSERT和UPDATE多对多的关系
问题= db.Issues.Include(创),其中(x => x.IssueId == issue.IssueId)。单();
issue.Creators = db.Creators.Where(X => CreatorIds.Contains(x.CreatorId))了ToList();
db.Entry(问题).STATE = System.Data.EntityState.Modified;
db.SaveChanges(); 返回RedirectToAction(「指数」);
} IssueEditModel issueEdit =新IssueEditModel {
创作者= db.Creators.ToList(),
问题=的问题,
};
返回查看(issueEdit);
}
模型绑定没有加载它们适合你 - 你的问题对象从视图未来不会神奇包含它们,除非你的一切设置正确绑定
在没有看到你的观点不能说为什么,但我只想说你必须装载它们,然后将其删除。您可以加载一个新的问题,对象,然后就TryUpdateModel(问题)来获取更新到该模型的形式值。然后删除每个issues.Creators(如果多数民众赞成预期的动作)
如果(ModelState.IsValid)
{ VAR issueFromDb = db.Issues.Where(X =>此标准);
布尔updateSuccessful = TryUpdateModel(issueFromDb);
的foreach(在issueFromDb.Creators VAR的创造者)
{
//删除创建者如果多数民众赞成你想要什么
}
不过,如果你只是希望所有的创作者来自于页面返回不加载,请绑定到一个枚举。有很多帖子在那里此,继承人之一:ASP.NET MVC3模型绑定使用的IEnumerable(不能推断型)
如果关系是存在的,创作者应自动仅仅通过加载问题加载。你并不需要只加载的创造者。加载完整的模型,以确保其工作和我一样在编辑以上。您code'应'的工作好,但其可能需要.INCLUDE(创)试试这个:
VAR testIssue =邻在db.Issues.Include(创作者)
其中,o.IssueId == issue.IssueId
选择o;
的foreach(在testIssue.Creators VAR的创造者)
{
//检查的创造者
}
这会让你知道,如果创作者正确加载。
I am having a really hard time updating and deleting many to many relationships with EF Code-first.
I have a fairly simple Model:
public class Issue
{
[Key]
public int IssueId { get; set; }
public int Number { get; set; }
public string Title { get; set; }
public DateTime Date { get; set; }
public virtual ICollection<Creator> Creators { get; set; }
}
public class Creator
{
[Key]
public int CreatorId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Issue> Issues { get; set; }
}
public class Icbd : DbContext
{
public DbSet<Issue> Issues { get; set; }
public DbSet<Creator> Creators { get; set; }
}
I have been unable to figure out how to update the many-to-many realtionship using the EF context. In my isnert/update action, I have this code:
[HttpPost]
public ActionResult EditIssue ( Issue issue, int[] CreatorIds )
{
if(CreatorIds == null)
ModelState.AddModelError("CreatorIds", "Please specify at least one creator");
if(ModelState.IsValid)
{
// insert or update the issue record (no relationship)
if (issue.IssueId == 0)
db.Issues.Add(issue);
else
db.Entry(issue).State = System.Data.EntityState.Modified;
db.SaveChanges();
// delete - delete current relationships
if (issue.Creators != null)
{
issue.Creators = new List<Creator>();
db.Entry(issue).State = System.Data.EntityState.Modified;
db.SaveChanges();
}
// insert - get creators for many-to-many realtionship
issue.Creators = db.Creators.Where(x => CreatorIds.Contains(x.CreatorId)).ToList();
db.Entry(issue).State = System.Data.EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
IssueEditModel issueEdit = new IssueEditModel{
Creators = db.Creators.ToList(),
Issue = issue,
};
return View(issueEdit);
}
I can insert Issues
and I can insert new issue.Creators
without a problem. But, when I am trying to delete the current issue.Creators
so I can then insert the new ones, issue.Creators
is ALWAYS null so it will never update to an empty list. I don't understand this. issue.Creators
has records in it because when the code proceeds to insert the new creators, I get an error like this:
Violation of PRIMARY KEY constraint 'PK__CreatorI__13D353AB03317E3D'. Cannot insert duplicate key in object 'dbo.CreatorIssues'.
The statement has been terminated.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.SqlClient.SqlException: Violation of PRIMARY KEY constraint 'PK__CreatorI__13D353AB03317E3D'. Cannot insert duplicate key in object 'dbo.CreatorIssues'.
The statement has been terminated.
Source Error:
Line 59: issue.Creators = db.Creators.Where(x => CreatorIds.Contains(x.CreatorId)).ToList();
Line 60: db.Entry(issue).State = System.Data.EntityState.Modified;
Line 61: db.SaveChanges();
Line 62:
Line 63: return RedirectToAction("Index");
How do I get issue.Creators
to accurately show the current relationships so I can delete them?
Update: Working Controller
[HttpPost]
public ActionResult EditIssue ( Issue issue, int[] CreatorIds )
{
if(CreatorIds == null)
ModelState.AddModelError("CreatorIds", "Please specify at least one creator");
if(ModelState.IsValid)
{
// insert or update the issue record (no relationship)
if (issue.IssueId == 0)
db.Issues.Add(issue);
else
db.Entry(issue).State = System.Data.EntityState.Modified;
db.SaveChanges();
// insert and update many to many relationship
issue = db.Issues.Include("Creators").Where(x => x.IssueId == issue.IssueId).Single();
issue.Creators = db.Creators.Where(x => CreatorIds.Contains(x.CreatorId)).ToList();
db.Entry(issue).State = System.Data.EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
IssueEditModel issueEdit = new IssueEditModel{
Creators = db.Creators.ToList(),
Issue = issue,
};
return View(issueEdit);
}
The model binder isn't loading them up for you - your issues object coming from the view won't magically contain them unless you setup everything up properly for binding.
Without seeing your view one can't say why, but suffice to say you'll have to load them up, then delete them. You can load a new issues object and then do TryUpdateModel(issues) to get the form values updated into that model. Then delete each issues.Creators (if thats the intended action)
if(ModelState.IsValid)
{
var issueFromDb = db.Issues.Where(x => criteria here);
bool updateSuccessful = TryUpdateModel(issueFromDb);
foreach(var creator in issueFromDb.Creators)
{
//delete creator if thats what you want
}
However if you just want all of your creators to come back from the page without loading, check out binding to an enumerable. there are many posts out there on this, heres one: ASP.NET MVC3 Model Binding using IEnumerable (Cannot infer type from)
If the relationship is there, the Creators should automatically load just by loading the Issue. You don't need to load only the creators. Load your full model to be sure its working as I did in the edit above. Your code 'should' work ok but its possible you need to .Include("Creators") try this:
var testIssue = from o in db.Issues.Include("Creators") where o.IssueId == issue.IssueId select o; foreach(var creator in testIssue.Creators) { //check creator }
this will let you know if "Creators" is loading properly.
这篇关于如何与实体框架code-首先执行CRUD?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!