FoodItem と FoodItemCategory のモデルを持つ MVC3 C# プロジェクトがあります。2 つのモデルは次のように表示されます。
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 プロパティでその特定のカテゴリをチェックします。存在する場合は、チェックボックスの checked プロパティを設定します。チェックボックスをオンにして [保存] をクリックすると、コントローラーの 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 行目: return RedirectToAction("Index"); 101 行目: }
問題があるかどうかはわかりませんが、SQLServer Compact Edition 4 を使用しています。これは正しい方法ですか? このようなものの通常のコーディング方法は何ですか? この同じ関係モデルがブログなどの多くの状況で使用されているため、これと同じ状況が毎日発生していることはわかっています。