У меня есть проект 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; }
}
У меня есть представление _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]
Описание: во время выполнения текущего веб-запроса произошло необработанное исключение. Пожалуйста, просмотрите трассировку стека для получения дополнительной информации об ошибке и о том, где она возникла в коде.
Сведения об исключении: System.Data.SqlServerCe.SqlCeException: дублирующее значение не может быть вставлено в> уникальный индекс. [Имя таблицы = FoodItemCategoryFoodItems, Имя ограничения => PK_ FoodItemCategoryFoodItems _00000000000000A8]
Ошибка источника:
Строка 97: context.Entry (foodItem) .State = EntityState.Modified;
Строка 98: foodItem.Categories = Categories;
Строка 99: context.SaveChanges ();
Строка 100: return RedirectToAction («Индекс»);
Строка 101:}
Не уверен, имеет ли это значение, но я использую SQLServer Compact Edition 4. Правильно ли я поступаю? Какова нормальная практика кодирования для чего-то подобного? Я знаю, что такая же ситуация возникает ежедневно, так как эта же модель отношений используется во многих ситуациях, таких как блоги и т. Д.