Asp.net mvc 实体框架4未保存多对多行
希望是一个非常简单的问题。但我首先在MVC应用程序中使用代码,我有一个Category和ServiceType对象,它们具有多对多关系:Asp.net mvc 实体框架4未保存多对多行,asp.net-mvc,entity-framework,many-to-many,ef-code-first,Asp.net Mvc,Entity Framework,Many To Many,Ef Code First,希望是一个非常简单的问题。但我首先在MVC应用程序中使用代码,我有一个Category和ServiceType对象,它们具有多对多关系: public class Category { public Category() { ServiceTypes = new HashSet<ServiceType>(); } public Guid CategoryId { get; set; } [Required(ErrorMess
public class Category
{
public Category()
{
ServiceTypes = new HashSet<ServiceType>();
}
public Guid CategoryId { get; set; }
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
public virtual ICollection<ServiceType> ServiceTypes { get; set; }
}
我希望我在这里做错了什么。有什么想法吗
谢谢
编辑:
虽然下面的回答确实是正确的,但我认为我应该添加以下最终版本的Edit post方法:
[HttpPost]
public ActionResult Edit(Category category, Guid[] serviceTypeIds)
{
if (ModelState.IsValid)
{
// Must set to modified or adding child records does not set to modified
db.Entry(category).State = EntityState.Modified;
// Force loading of ServiceTypes collection due to lazy loading
db.Entry(category).Collection(st => st.ServiceTypes).Load();
// Clear existing ServiceTypes
category.ServiceTypes.Clear();
// Set checked ServiceTypes
if (serviceTypeIds != null)
{
foreach (Guid serviceType in serviceTypeIds)
{
ServiceType st = db.ServiceTypes.Find(serviceType);
category.ServiceTypes.Add(st);
}
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(category);
}
请注意强制加载ServiceTypes集合的那一行,这是必需的,因为延迟加载不包括那些子项,这意味着清除ServiceTypes集合没有任何作用。尝试移动将类别附加到循环前面上下文的那一行:
[HttpPost]
公共操作结果编辑(类别,Guid[]ServiceTypeId)
{
if(ModelState.IsValid)
{
//清除现有服务类型
category.ServiceTypes.Clear();
db.Entry(category).State=EntityState.Modified;
//类别已附加,状态已修改
//添加选中的服务类型
foreach(ServiceTypeId中的Guid serviceType)
{
ServiceType st=db.ServiceTypes.Find(ServiceType);
//st已附加,状态不变
类别.服务类型.添加(st);
//EF将检测到这是类别的更改,并创建SQL
//调用SaveChanges时向链接表添加行的步骤
}
db.SaveChanges();
返回操作(“索引”);
}
返回视图(类别);
}
在您的代码中,EF没有注意到您添加了servicetypes,因为当servicetypes已经在
类别中时,您将类别附加到上下文。servicetypes
集合和所有servicetypes已经在状态Unchanged
下附加到上下文。谢谢Slauma,这正是问题所在。虽然您的答案现在正确地将条目保存到数据库中,但我发现,当输入Edit httppost方法时,category.ServiceTypes计数为0,即使在Edit response方法上它肯定包含1个已保存的ServiceType。知道是什么原因吗?@Gary:这可能是MVC modelbinder的问题。对我来说,category.ServiceTypes
是否包含某些内容并不重要,因为您要做的第一件事就是清除该列表。重要的是只有Guid[]serviceTypeIds
集合,因为您使用Find
从数据库加载ServiceType,然后创建与加载实体的关联。问题是因为MVC Modelbinder中的类别不包含任何ServiceType(即使它们存在于数据库中)Clear方法没有任何作用。因此,它实际上试图在CategoryServiceTypes中添加一个重复的子行,但显然失败了。你知道为什么MVC Modelbinder中的集合是空的吗?@Gary:不知道。需要更详细地查看视图代码。如果我理解正确,您的视图不仅应该添加category和servicetype之间的关系,还应该删除关系?基本上,您必须比较数据库中的内容和视图中的内容(在Guid集合中?),以检测添加、删除和未更改的内容。可能您需要这样的东西:(特别是答案中的最后一个代码片段)。也许可以创建一个新问题来更详细地描述问题。
[HttpPost]
public ActionResult Edit(Category category, Guid[] serviceTypeIds)
{
if (ModelState.IsValid)
{
// Must set to modified or adding child records does not set to modified
db.Entry(category).State = EntityState.Modified;
// Force loading of ServiceTypes collection due to lazy loading
db.Entry(category).Collection(st => st.ServiceTypes).Load();
// Clear existing ServiceTypes
category.ServiceTypes.Clear();
// Set checked ServiceTypes
if (serviceTypeIds != null)
{
foreach (Guid serviceType in serviceTypeIds)
{
ServiceType st = db.ServiceTypes.Find(serviceType);
category.ServiceTypes.Add(st);
}
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(category);
}