2013-04-30 44 views
0

我有一個項目,我使用EntityFramework Code First來管理數據庫。 是我使用這個該機型如下:如何在EntityFramework中引用另一個模型列表的模型映射代碼優先

[Table("Data")] 
public class Data 
{ 
    [Key, Column("Id")] 
    public int Id { get; set; } 

    [Column("Code")] 
    public string Code { get; set; } 

    [Column("Name")] 
    public string Name { get; set; } 

    [Column("Description")] 
    public string Description { get; set; } 

    public virtual List<DataAttribute> Attributes { get; set; } 
} 

[Table("DataAttribute")] 
public class DataAttribute 
{ 
    [Key, Column("Id")] 
    public int Id { get; set; } 

    [Column("IdData"), ForeignKey("Data")] 
    public int IdData { get; set; } 

    [Column("Name")] 
    public string Name { get; set; } 

    [Column("Description")] 
    public string Description { get; set; } 

    public virtual Data Data { get; set; } 
} 

我與此遇到的問題是,當我嘗試編輯一個數據對象(及其相關的一起DataAttribute值)。使用Data元素和DataAttribute元素提交表單時,我沒有正確映射它。我舉一個.cshtml文件的例子。

@model MVCTestApp.Models.Data 
@{ 
    ViewBag.Title = "Edit"; 
} 
@section Scripts { 
    <script type="text/javascript"> 
     $(function() { 
      $('#new-row').click(function() { 
       $('table tbody').append(
        '<tr>' + 
        '<td><input class="name" type="text" /></td>' + 
        '<td><input class="description" type="text" /></td>' + 
        '<td><a class="delete" href="#">Delete</a></td>' + 
        '</tr>' 
       ); 
       $('.delete').click(function() { 
        $(this).parent().parent().remove(); 
       }); 
      }); 
     }); 
    </script> 
} 
@using (@Html.BeginForm("Edit", "Data", FormMethod.Post)) { 
    @Html.HiddenFor(a => a.Id) 
Name: 
    <br /> 
    @Html.TextBoxFor(a => a.Name) 
    <br /> 
Description: 
    <br /> 
    @Html.TextBoxFor(a => a.Description) 
    <br /> 
Code: 
    <br /> 
    @Html.TextBoxFor(a => a.Code) 
    <br /> 
    <table> 
     <thead> 
      <tr> 
       <th> 
        Name 
       </th> 
       <th> 
        Description 
       </th> 
       <th> 
       </th> 
      </tr> 
     </thead> 
     <tbody> 
      <tr> 
       <td> 
        <a id="new-row" href="#">New Row</a> 
       </td> 
       <td colspan="2"> 
       </td> 
      </tr> 
      @if (Model != null) { 
       foreach (var item in Model.Attributes) { 
        <tr> 
         @Html.HiddenFor(b => item.Id) 
         @Html.HiddenFor(b => item.IdData) 
         <td class="name">@Html.TextBoxFor(b => item.Name) 
         </td> 
         <td class="description">@Html.TextBoxFor(b => item.Description) 
         </td> 
         <td> 
          <a class="delete" href="#">Delete</a> 
         </td> 
        </tr> 
       } 
      } 
     </tbody> 
    </table> 
    <input type="submit" value="submit" /> 
} 

問題是這樣的。

如何讓EntityFramework在發佈時識別控制器上的DataAttributes列表?

下面是我現在使用的代碼。

[HttpPost] 
    [AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult Edit(Data model) 
    { 
     if (model != null) { 

      db.Data.Add(model); //model has the model.Attributes list set as null 
      db.SaveChanges(); 

      return View("Index", db.Data.OrderBy(a => a.Id).ToList()); 
     } 
     return View(); 
    } 

在此先感謝您。

+1

您需要確保列表中的序列化,當你發送回控制器。您也可以嘗試設置返回的包含列表的特定ViewModel。 – Nomad101 2013-04-30 00:49:36

+0

我會如何序列化它?通過使它成爲一個json對象或類似的東西,然後將它傳遞給控制器​​? – triangulito 2013-04-30 00:50:51

+0

這可以很容易地工作,我會做的是向ActionResult添加一個參數,並將其設置爲字符串並使用內置的json解析器來獲取值並設置模型屬性。您可以在客戶端上使用JSON序列化要發回的對象。 – Nomad101 2013-04-30 00:53:56

回答

0

爲了解決這個問題,我做了以下操作:將視圖上的foreach改爲for和used Attributes [i],以便它可以使用它創建輸入(這是Controller實際接收值的原因)並且我還改變了新行的創建方式,以便他們也可以使用相同的命名約定並傳遞給控制器​​。

這是新的觀點:

@model MVCTestApp.Models.Data 
@{ 
    ViewBag.Title = "Edit"; 
} 
@section Scripts { 
    <script type="text/javascript"> 
     $(function() { 
      $('#new-row').click(function() { 
       var counter = $("#counter").val(); 
       counter++; 
       $('table tbody').append(
        '<tr>' + 
        '<td><input id="Attributes_' + counter + '__Name" ' + 
        'name="Attributes[' + counter + '].Name" type="text" /></td>' + 
        '<td><input id="Attributes_' + counter + '__Description" ' + 
        'name="Attributes[' + counter + '].Description" type="text" /></td>' + 
        '<td><a class="delete" href="#">Delete</a></td>' + 
        '</tr>' 
       ); 
       $('.delete').click(function() { 
        $(this).parent().parent().remove(); 
       }); 
       $("#counter").val(counter); 
      }); 
     }); 
    </script> 
} 
@using (@Html.BeginForm("Edit", "Data", FormMethod.Post)) { 
    var counter = 0; 
    @Html.HiddenFor(a => a.Id) 
Name: 
    <br /> 
    @Html.TextBoxFor(a => a.Name) 
    <br /> 
Description: 
    <br /> 
    @Html.TextBoxFor(a => a.Description) 
    <br /> 
Code: 
    <br /> 
    @Html.TextBoxFor(a => a.Code) 
    <br /> 
    <table> 
     <thead> 
      <tr> 
       <th> 
        Name 
       </th> 
       <th> 
        Description 
       </th> 
       <th> 
       </th> 
      </tr> 
     </thead> 
     <tbody> 
      <tr> 
       <td> 
        <a id="new-row" href="#">New Row</a> 
       </td> 
       <td colspan="2"> 
       </td> 
      </tr> 
      @if (Model != null) { 
       for (int i = 0; i < Model.Attributes.Count; i++) { 
        <tr> 
         @Html.HiddenFor(a => a.Attributes[i].Id) 
         @Html.HiddenFor(a => a.Attributes[i].IdData) 
         <td>@Html.TextBoxFor(a => a.Attributes[i].Name)</td> 
         <td>@Html.TextBoxFor(a => a.Attributes[i].Description)</td> 
         <td> 
          <a class="delete" href="#">Delete</a> 
         </td> 
        </tr> 
        counter = i; 
       } 
      } 
     </tbody> 
    </table> 
    <input type="submit" value="submit" /> 
    @Html.Hidden("counter", counter.ToString()); 
} 
0

首先你需要了解一些事情。 第一個問題是,爲什麼要先編碼?你給我們沒有理由不建立SQL模型並用EF工具導入。然後,您需要了解ModelBinder機制如何工作。您發送帶有參數的http發佈請求,每個參數都帶有一個名稱,並希望將其綁定到Model類。 ModelBinder試圖在Model類中查找這些名稱,如果您有大量具有相同名稱的參數,則該名稱將永遠不會發生。此類屬性稱爲導航屬性,它們應該由EF加載或以分隔的形式加載。

例如,您嘗試使用一種形式來構建具有多個DataAttributes的Data對象。爲什麼不先創建Data對象,然後在另一個視圖中添加DataAttibutes?這就是MVC的全部內容。不同的模型 - >不同的控制器 - >不同的視圖。

如果你不分離責任,你會面臨更多的麻煩。

+0

我們首先使用代碼是因爲我們會對數據庫進行大量更改,並重新創建edmx文件並將其更新到服務器會花費太長時間纔能有用。我也在同一頁面上執行Data和DataAttributes,因爲DataAttributes只存在於數據內部進行修改,它們是它的一部分,對我來說製作另一個控制器,視圖和所有內容都沒有意義編輯它們。我正在嘗試正確創建它們,以便將它們傳遞迴控制器,並且我認爲我已經發現如果它是正確的,將會發布。 – triangulito 2013-04-30 16:51:19

+0

您的解決方案不是非常好。你正在創造一種毫無意義的新模式。不能保證DataEdit對象中的DataAttribute屬於數據。是的,你可以放心,但用戶可以強制黑客入侵。你只是添加一個不存在的新模型。 您應該重新考慮MVC的工作原理以及它代表什麼以及如何構建您的應用程序。這是一種解決方法,而不是解決方案。 – 2013-04-30 18:11:17

+0

如果再仔細考慮一下,ViewModel應該不是必須的,你說得對,但是從用戶的角度來看,功能確實有意義。 – triangulito 2013-04-30 19:00:02

相關問題