2017-10-20 16 views
1

私は複雑なモデルを作成し、フォームデータをデータベースに追加/更新する方法を見つけるためにしばらくの間苦労しています。私はModelClass1のための足場のCRUDコントローラを作成し、1つの編集クラスを使用して、すべての3つのエンティティを更新しようとしているMVC5 /エンティティ|複雑なモデルの更新/作成

namespace Models 
{ 
    public class ModelClass1 
    { 
     public int Id { get; set; } 
     public string Prop1 { get; set; } 
     public string Prop2 { get; set; } 

     public ICollection<ModelClass2> ModelClass2 { get; set; } 
    } 
    public class ModelClass2 
    { 
     public int Id { get; set; } 
     public string Prop3 { get; set; } 
     public string Prop4 { get; set; } 

     public ICollection<ModelClass3> ModelClass3 { get; set; } 
    } 

    public class ModelClass3 
    { 
     public int Id { get; set; } 
     public string Prop5 { get; set; } 
     public string Prop6 { get; set; } 
    } 
} 

は基本的に私のモデルは、以下のいずれかのように見えます。

私の編集(取得/ポスト)クラス:

// GET 
public ActionResult Edit(int? id) 
{ 
    if (id == null) 
    { 
     return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
    } 

    ModelClass1 ModelClass1 = db.ModelClass1 
     .Include(i => i.ModelClass2.Select(c => c.ModelClass3)) 
     .Where(x => x.Id == id) 
     .Single(); 

    if (config == null) 
    { 
     return HttpNotFound(); 
    } 
    return View(ModelClass1); 
} 


// POST 
[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Edit(ModelClass1 ModelClass1) 
{ 
    if (ModelState.IsValid) 
    { 
     db.Entry(ModelClass1).State = EntityState.Modified; 
     db.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 
    return View(ModelClass1); 
} 

私はEdi.cshtmlは次のようになりますので、編集ビュー内のフォームを移入するエディタテンプレートを使用することを選択した:

@model ModelClass1 

@using (Html.BeginForm()) 
{ 
    @Html.AntiForgeryToken() 
    <div class="form-horizontal"> 
     @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 
     @Html.HiddenFor(model => model.Id) 

     <div class="form-group"> 
      @Html.LabelFor(model => model.Prop1, htmlAttributes: new { @class = "control-label col-md-2" }) 
      <div class="col-md-10"> 
       @Html.EditorFor(model => model.Prop1, new { htmlAttributes = new { @class = "form-control" } }) 
       @Html.ValidationMessageFor(model => model.Prop1, "", new { @class = "text-danger" }) 
      </div> 
     </div> 

     <div class="form-group"> 
      @Html.LabelFor(model => model.Prop2, htmlAttributes: new { @class = "control-label col-md-2" }) 
      <div class="col-md-10"> 
       @Html.EditorFor(model => model.Prop2, new { htmlAttributes = new { @class = "form-control" } }) 
       @Html.ValidationMessageFor(model => model.Prop2, "", new { @class = "text-danger" }) 
      </div> 
     </div> 

     @Html.EditorFor(model => model.ModelClass2, new { htmlAttributes = new { @class = "form-control" } }) 

     @Html.EditorFor(model => model.ModelClass2.FirstOrDefault().ModelClass3, new { htmlAttributes = new { @class = "form-control" } }) 

    </div> 

    <div class="form-group"> 
     <div class="col-md-offset-2 col-md-10"> 
      <input type="submit" value="Save" class="btn btn-default" /> 
     </div> 
    </div> 
} 
以下のような私の3つのモデルクラスのそれぞれについて、

そして、作成したテンプレート:

@model ModelClass2 
<div class="form-group"> 
    @Html.LabelFor(model => model.Prop3, htmlAttributes: new { @class = "control-label col-md-2" }) 
    <div class="col-md-10"> 
     @Html.EditorFor(model => model.Prop3, new { htmlAttributes = new { @class = "form-control" } }) 
     @Html.ValidationMessageFor(model => model.Prop3, "", new { @class = "text-danger" }) 
    </div> 
</div> 

<div class="form-group"> 
    @Html.LabelFor(model => model.Prop4, htmlAttributes: new { @class = "control-label col-md-2" }) 
    <div class="col-md-10"> 
     @Html.EditorFor(model => model.Prop4, new { htmlAttributes = new { @class = "form-control" } }) 
     @Html.ValidationMessageFor(model => model.Prop4, "", new { @class = "text-danger" }) 
    </div> 
</div> 

データがBであります「ModelClass3」のために失敗したタイプのエンティティをアタッチ

:私はフォーム内のデータを変更し、HTTPPost Editメソッドを呼び出し、それを投稿したときに、正しく、私は、私は以下のエラーを受け取る編集コントローラを呼び出すことが、よ示さeing同じタイプの別のエンティティはすでに同じ主キー値を持っています。これは、「Attach」メソッドを使用するか、またはグラフ内のエンティティのいずれかが競合するキー値を持つ場合、エンティティの状態を「Unchanged」または「Modified」に設定すると発生します。これは、一部のエンティティが新しく、データベース生成キー値をまだ受け取っていないことが原因です。この場合、 'Add'メソッドまたは 'Added'エンティティ状態を使用してグラフを追跡し、非新規エンティティの状態を 'Unchanged'または 'Modified'に適切に設定します。

コントローラ/ビューからModelClass3を完全に削除してもエラーは発生しませんが、変更されたデータはデータベースに保存されません。

私のアプローチは最高のものではないと確信していますので、私はアイデアがなくなり、どんな助けにも大いに感謝します。

答えて

1

まず、フロントエンドでドメインエンティティを直接操作することはお勧めしません。あなたのドメインエンティティ用にView Model(VM)を作成します。いずれにしても、

このエラーは、おそらくエンティティがコンテキストに接続されていないために報告されています。私はDBからエンティティをフェッチして、プロパティの更新最初好むしかし

// POST 
[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Edit(ModelClass1 ModelClass1) 
{ 
    if (ModelState.IsValid) 
    { 
     db.Attach(ModelClass1); 
     db.Entry(ModelClass1).State = EntityState.Modified; 
     db.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 
    return View(ModelClass1); 
} 

:返信用

// POST 
[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Edit(ModelClass1 ModelClass1) 
{ 
    if (ModelState.IsValid) 
    { 
     ModelClass1 entityFromDB = db.ModelClass1 
      .Include(i => i.ModelClass2.Select(c => c.ModelClass3)) 
      .Where(x => x.Id == id) 
      .Single(); 
     MapProperties(entityFromDB, ModelClass1); // You could use a mapper (Auto Mapper) 
     db.Entry(ModelClass1).State = EntityState.Modified; 
     db.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 
    return View(ModelClass1); 
} 
+0

おかげで、私は考え出しだから、修正に状態を設定する前に、それを添付しなければなりません私は完全に私のアプリケーションを再構築し、automapperを使用して開始する必要があります。私はより構造的なdesingを発見した:https://www.pluralsight.com/guides/microsoft-net/asp-net-mvc-creating-solutions-with-separate -projects-for-entities-data-access-and-website-functionality – Alex

関連する問題