2009-05-21 116 views
12

我一起使用ASP.NET MVC和ADO.NET實體框架。實體框架與強類型MVC

我希望我的視圖和控制器強類型。

但我該如何處理實體關聯?

下面是一個簡單的例子:

一個人有一個部門。一個部門有零個或更多的人。

Entity Data Model of Person and Department entities

我的控制器通過一個Person對象的實例,所有的部門對象的視圖的集合。

public class PersonController : Controller 
{ 
    ... 

    // 
    // GET: /Person/Create 

    public ActionResult Create() 
    { 
     Person Model = new Person(); 
     Model.Id = Guid.NewGuid(); 
     ViewData["Departments"] = db.Department; 
     return View(Model); 
    } 
    ... 
} 

我的視圖有一個「部門」DropDownList與所有部門作爲選項。

<% using (Html.BeginForm()) {%> 

    <fieldset> 
     <legend>Fields</legend> 
     <p> 
      <label for="Id">Id:</label> 
      <%= Html.TextBox("Id") %> 
      <%= Html.ValidationMessage("Id", "*") %> 
     </p> 
     <p> 
      <label for="Name">Name:</label> 
      <%= Html.TextBox("Name") %> 
      <%= Html.ValidationMessage("Name", "*") %> 
     </p> 
     <p> 
      <label for="Department">Family:</label> 
      <%= Html.DropDownList("Department", new SelectList((IEnumerable)ViewData["Departments"], "Id", "Name"))%> 
      <%= Html.ValidationMessage("Department", "*")%> 
     </p> 
     <p> 
      <input type="submit" value="Create" /> 
     </p> 
    </fieldset> 

<% } %> 

但是,貼到控制器的Person對象任何部門和失敗!

public class PersonController : Controller 
{ 
    ... 

    // 
    // POST: /Person/Create 

    [AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult Create(Person Model) 
    { 
     try 
     { 
      db.AddToPerson(Model); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
     catch 
     { 
      return View(); 
     } 
    } 
    ... 
} 

爲什麼不從DropDownList中選定的部門「部門」自動添加到模型的人嗎?

如何在強類型的視圖和控制器中使用ADO.NET實體框架和ASP.NET MVC?

+0

http://stackoverflow.com/questions/922402/strongly-typed-asp-net-mvc-with -ado-net-entity-framework – 2009-05-28 18:13:50

回答

2

我還沒有發現開箱即用的DropDownList幫助器與模型綁定非常協調。我始終必須從ViewData中獲取DropDownList的值,並在將更改提交到存儲庫或數據庫之前,手動將值映射到我的控制器中。

大部分時間我使用DropDownList來顯示自定義類型關係的選項(例如人員的部門)。 MVC無法知道如何簡單地根據列表中選定項目的值來映射對象。相反,您必須使用選定的值來抓取該實體並自行映射它。我不知道這是否是問題所在,而且我還沒有嘗試使用簡單的類型作爲選項(例如購買產品的數量或類似的東西),將列表綁定到模型上,但我會很好奇瞭解更多關於這個特定問題以及其他人如何使用下拉列表管理模型綁定的信息。

+0

我不認爲你的問題是孤立的使用EF與MVC。我有使用POCO的相同問題。 – nkirkes 2009-05-21 22:13:35

5

我會盡力引導你從MVC的一面,這就是問題的所在,我相信

在創建Person對象和部門從數據庫列表中的Create()方法,然後這兩個對象都被傳遞給View。視圖從Department列表中獲取數據並使用它來呈現HTML表單 - 僅使用Id和Name。

在接下來的步驟中,表單將作爲值鍵對(標準POST)的集合提交給服務器。路由引擎從action屬性中獲取請求的url並將其解析爲PersonController.Create(Person Model)操作。此方法的參數是Person,因此數據綁定器將啓動,創建Person類的新實例並嘗試將傳入數據與Person的屬性進行匹配。在Department的情況下,傳入值是部門的Id(因爲這是您爲DropDownList設置的值成員),而Person類中的財產部門可能是部門類型。這是不匹配的,所以它不能填充該屬性,而是留空。

正如您所看到的,這不是DropDownList的限制,問題在於您無法將所有Department數據傳遞給DropDownList,並且在保存過程中(如使用Person)重新創建它,這是由於POST的性質請求,這就是爲什麼DropDownList僅從每個部門(值和名稱)獲取兩個值的原因。我通常的解決方案是:通常我的模型與我的業務對象不同,我通過在模型上具有兩個屬性來完成此操作:只獲取IEnumerable屬性和另一個DepartmentId屬性(get/set)。然後我用這樣的:

<%= Html.DropDownList("DepartmentId", Model.Departments) %> 

然後在攢動,我從DB使用DepartmentID的搶部,將其分配給個人和保存。

在你的情況下(模型是業務對象),我可能不會嘗試自動將部門綁定到人員模型,但只需獲取Id並自行完成。

這只是一個猜測(我不是EF專家),但我認爲你可能在這裏有另一個問題:如果數據庫是控制器上的字段,並且在每次請求時重新創建,這可能是一些不必要的開銷我希望它不會每次打開數據庫連接,請檢查它。

希望幫助

3

我使用一個ViewModel(檢查出的NerdDinner教程,在底部的引用)。

首先,通過在局部擴展模型需要假外鍵約束:

public partial class Person 
{ 
    public int DepartmentId 
    { 
    get 
    { 
     if(this.DepartmentsReference.EntityKey == null) return 0; 
     else 
     return (int)this.DepartmentsReference.EntityKey.EntityKeyValues[0].Value; 
    } 
    set 
    { 
     this.DepartmentsReference.EntityKey = 
      new EntityKey("YourEntities.DepartmentSet", "Id", value); 
    } 
    } 
} 

二,創建視圖模型:

public class PersonFormViewModel 
{ 
    public SelectList Departments { get; set: } 
    public Person Pers { get; set; } 

    public PersonFormViewModel(Person p, List<Department> departments) 
    { 
    this.Pers = p; 
    this.Departments = new SelectList(departments, "Id", "Name", p.DepartmentId); 
    } 
} 

第三,控制器動作(縮寫創建例子):

public ActionResult Create() 
{ 
    YourEntities entities = new YourEntities(); 
    List<Department> departments = entities.DepartmentSet.ToList(); 
    PersonFormViewModel viewModel = 
    new PersonFormViewModel(new Person(), departments); 
    return View(modelView); 
}  

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create([Bind(Exclude="Id")]Person personToCreate 
{ 
    YourEntities entities = new YourEntities(); // Probably not instantiated here 
    entities.AddToPersonSet(personToCreate); 
    entities.SaveChanges(); 
    redirectToAction("Index"); 
} 

四,查看摘錄:

<p> 
    <label for="Name">Name:</label> 
    <%= Html.TextBox("Name", Model.Pers.Name) %> 
    <%= Html.ValidationMessage("Name", "*") %> 
</p> 
<p> 
    <label for="DepartmentId">Family:</label> 
    <%= Html.DropDownList("DepartmentId", Model.Departments)%> 
    <%= Html.ValidationMessage("DepartmentId", "*")%> 
</p> 

參考文獻:

+0

應該有一個更簡單的方法。 MVC 2是否有解決方案?想象一下,你爲每個外部id像DeparmentId創建一個假外鍵。我們的代碼變得有點混亂。 :-( – 2010-02-23 17:30:47