2009-05-21 12 views
12

私は、ASP.NET MVCとADO.NET Entity Frameworkを一緒に使用しています。厳密に型付けされたMVCを持つEntity Framework

私のビューとコントローラは厳密にタイプしたいと思っています。

エンティティの関連付けをどのように処理する必要がありますか?

ここに簡単な例を示します。

人には1つの部門があります。部署には0人以上の人がいます。

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

マイビューには、すべての部門をオプションとして含む「部門」ドロップダウンリストがあります。

<% 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 –

答えて

2

すぐに使えるDropDownListヘルパーがモデルバインドでうまく動作することはわかりませんでした。 ViewDataからDropDownListの値を取得し、リポジトリまたはdbへの変更をコミットする前にコントローラの値を手動でマップする必要があります。

私はDropDownListを使用して、カスタムタイプの関係のオプションを表示しています(Departments for a Personなど)。 MVCは、単にリスト内の選択された項目の値に基づいてオブジェクトをマップする方法を知ることができません。むしろ、選択した値を使用してそのエンティティを取得し、それを自分自身でマップする必要があります。私はそれがここの問題かどうか分かりません。オプションとして単純なタイプのモデル(例えば、購入する製品の数量など)を持つモデルへのモデルバインドを試みたことはありませんが、私は好奇心が強いでしょうこの特定の問題と、他の人がドロップダウンリストを使ってモデルバインディングを管理している様子を知ることができます。

+0

あなたの問題は、MVCでEFを使用することとは区別されないと思います。私はPOCOを使って同じ問題を抱えています。 – nkirkes

5

問題がどこにあるか、これがあると、私はその後、私はあなたがPersonオブジェクトとデータベースから部門のリストを作成します()メソッドでは

を信じて、MVC側からあなたを案内しようとします両方のオブジェクトがViewに渡されます。ビューはDepartmentリストのデータを受け取り、IDと名前のみを使用してHTMLフォームをレンダリングします。

フォームは、値キーのコレクション(標準POST)としてサーバーに送信されます。ルーティングエンジンは、要求されたURLをaction属性から取得し、それをPersonController.Create(Person Model)アクションに解決します。このメソッドの引数はPersonなので、データバインダーが起動し、Personクラスの新しいインスタンスが作成され、Personのプロパティと入力データを照合しようとします。 Departmentの場合、着信する値はDepartmentのIDです(これはDropDownListの値メンバーとして設定されているためです)。PersonクラスのプロパティDepartmentはおそらくDepartmentタイプです。これは不一致なので、プロパティを埋めることができず、空のままです。

これはDropDownListの制限ではありません。問題は、DropDownListにすべてのDepartmentデータを渡すことができず、POSTの性質上、(Personのように)保存中にDepartmentデータを再作成できないことですDropDownListは各部門(値と名前)から2つの値しか取れない理由です。

私のいつもの解決策:通常、私のモデルは、私のビジネスオブジェクトと同じクラスではないとして、私は、モデル上の2つの特性を有することにより、次の操作を行いますのみのIEnumerableプロパティを取得し、別のDepartmentIdのプロパティ(取得/設定)。そして、私はこのようにそれを使用します。

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

[保存アクションで、私はDepartmentIdのを使用してDBから部門をつかむ、人にそれを割り当てて保存します。

あなたの場合(モデルはビジネスオブジェクトです)、私はDepartmentをPersonモデルに自動的にバインドしようとはしませんが、IDを取得して自分で行います。

これはまあまあです(私はEFスペシャリストではありません)が、ここに別の問題があると思います:dbがController上のフィールドであり、リクエストごとに再作成された場合、不要なオーバーヘッド。私はそれが毎回db接続を開いていないことを願って、それを確認してください。

私はViewModelには(NerdDinnerチュートリアル、下部の参照をチェックしてください)を使用

3

に役立ちます願っています。

まず、あなたは部分的にあなたのモデルを拡張して偽の外部キー制約する必要があります。

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

第二に、ViewModelにを作成します。

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

第三に、コントローラのアクションを(略し作成例):

第4ビューのスニペット:

<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にはそれに対する解決策がありますか? DeparmentIdのような外部IDごとに偽の外部キーを作成するとします。私たちのコードはちょっと混乱します。 :-( –

関連する問題