2017-10-20 71 views
1

我已經創建了一個複雜的模型並且一直在努力尋找一種方法來添加/更新表單數據到數據庫。MVC5/Entity |更新/創建複雜模型

基本上我的模型看起來像下面這樣:

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; } 
    } 
} 

我已經創造了ModelClass1支架CRUD控制器和嘗試更新使用一個編輯類中的所有3個實體。

我的編輯(GET/POST)類:

// 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 eing正確顯示然後我打電話編輯控制器,但是當我修改形式中的數據,並張貼調用HTTPPost編輯方法我收到以下錯誤:

附加類型的失敗,因爲一個實體「ModelClass3」另一個相同類型的實體已具有相同的主鍵值。如果圖中的任何實體具有衝突的鍵值,則使用「附加」方法或將實體的狀態設置爲「未更改」或「已修改」時可能會發生這種情況。這可能是因爲一些實體是新的並且還沒有收到數據庫生成的關鍵值。在這種情況下,使用'Add'方法或'Added'實體狀態來跟蹤圖形,然後根據情況將非新實體的狀態設置爲'Unchanged'或'Modified'。

如果我完全刪除ModelClass3從控制器/視圖我沒有收到任何錯誤,但修改後的數據沒有被保存到數據庫。

我很確定我的方法不是最好的方法,所以任何幫助將非常感激,因爲我沒有想法。

回答

1

首先,我不會推薦直接在前端使用您的域實體。我將爲您的域實體創建一個View Model(VM)。任何方式,

您報告的這個錯誤可能是由於實體沒有被附加到上下文。

// 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); 
} 

但是我寧願先取出由DB實體,然後更新的屬性:

// 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.I已經找到了更加結構化的設計:https://www.pluralsight.com/guides/microsoft-net/asp-net-mvc-creating-solutions-with-separate -projects換實體數據存取和網站的功能 – Alex