【发布时间】:2011-05-01 19:09:11
【问题描述】:
我有一个 MVC3 C# 项目,我有一个 FoodItem 和 FoodItemCategory 模型。两种模型如下所示:
public class FoodItem
{
public int ID { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<FoodItemCategory> Categories { get; set; }
public DateTime CreateDate { get; set; }
}
public class FoodItemCategory {
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<FoodItem> FoodItems { get; set; }
public DateTime CreateDate { get; set; }
}
我有一个最初从 Scaffolder 生成的 _CreateOrEdit.cshtml 视图,我对其进行了修改以包含所有类别并选中食物项所属的框。一个食品项目可以有许多或所有类别。视图如下所示:
@model StackOverFlowIssue.Models.FoodItem
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Description)
@Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Categories)
</div>
<div class="editor-field">
@foreach (var FoodItemCategory in (IEnumerable<StackOverFlowIssue.Models.FoodItemCategory>)ViewBag.Categories){
<input type="checkbox" name="FoodItemCategoryId" value="@FoodItemCategory.ID"
@foreach(var c in Model.Categories){
if(c.ID == FoodItemCategory.ID){
@String.Format("checked=\"checked\"")
}
}
/>
@FoodItemCategory.Name
<br />
}
</div>
@Html.Hidden("CreateDate", @DateTime.Now)
如您所见,我有一个嵌套循环,它为每个类别创建一个复选框,在创建每个类别时,我循环并检查模型的 Categories 属性中的特定类别。如果存在,我设置复选框的选中属性。如果您选中一个框并单击保存,则在控制器上的 HttpPost 操作上,我正在执行以下操作:
[HttpPost]
public ActionResult Edit(FoodItem foodItem)
{
if (ModelState.IsValid)
{
var cList = Request["CategoryId"].Split(',');
List<FoodItemCategory> categories = new List<FoodItemCategory>();
foreach (var c in cList) {
var ci = Convert.ToInt32(c);
FoodItemCategory category = context.FoodItemCategories.Single(x => x.ID == ci);
categories.Add(category);
}
context.Entry(foodItem).State = EntityState.Modified;
restaurant.Categories = categories;
context.SaveChanges();
return RedirectToAction("Index");
}
return View(foodItem);
}
我可以一次保存类别。如果我返回视图并单击保存,我会收到以下错误:
不能将重复值插入唯一索引。 [表名 = >FoodItemCategoryFoodItems,约束名 = PK_FoodItemCategoryFoodItems_00000000000000A8] 说明:执行当前 Web 请求期间发生未处理的异常。请>查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。
异常详细信息:System.Data.SqlServerCe.SqlCeException:无法将重复值插入 >唯一索引。 [表名 = FoodItemCategoryFoodItems,约束名称 = >PK_FoodItemCategoryFoodItems_00000000000000A8]
来源错误:
第 97 行:context.Entry(foodItem).State = EntityState.Modified; 第 98 行:foodItem.Categories = 类别; 第 99 行:context.SaveChanges(); 第 100 行:返回 RedirectToAction("Index"); 第 101 行:}
不确定这是否重要,但我使用的是 SQLServer Compact Edition 4。我这样做的方式是否正确?像这样的事情的正常编码实践是什么?我知道同样的情况每天都会发生,因为在博客等许多情况下都使用同样的关系模型。
【问题讨论】:
-
数据库表是使用唯一的 PK 创建的,它抱怨您正在添加重复项。我认为查看表创建 SQL 和 context.SaveChanges() 代码会有所帮助。
标签: c# asp.net-mvc-3 entity-framework-4 scaffolding sql-server-ce-4