2012-03-27 10 views
7

私はEF 4をプロジェクトに実装しています。その中には顧客と注文のテーブルがあります。 1つの顧客(顧客)から多くの顧客(注文)への関係があります。ViewModelの設計方法

私は両方の(CustomerViewModelとOrderViewModel)が私のドメイン層からインターフェース層(この場合はMVC)に渡すためのビューモデルを作成しています。

は今、「私はcustomerviewmodel、例えば?両方のviewmodelを参照する必要がありますされた質問はIEnumerable<OrderViewModel>を持っており、orderviewmodelでCustomerViewModelを持っています。IEnumerable<OrderViewModel>CustomerViewModelが移入されるようにので、どのように私は(ベストプラクティスとして)それを設計しなければ正しい参照?

+0

これが役立つかどうかを確認してください:http://blogs.teamb.com/craigstuntz/2009/12/31/38500/ –

+0

申し訳ありません。 – user384080

答えて

23

ドメインモデル(=エンティティ)の観点から決して、特定のビューを念頭に置いてViewModelsのデザインを運転します。ViewModelの外観は、表示するものとビューで変更したい場合

結果として、OrderViewModelとTHE CustomerViewModelは、注文や顧客またはその一部を表示または編集するビューが異なるためです。したがって、特定の目的とビューのために、したがって異なるバリエーションで複数回、それらのViewModelを持っています。

OrderEditViewがあり、このビューで注文情報を編集し、その注文の顧客を表示できるとします。あなたは、このようなOrderEditViewModelを持っているでしょう:

public class OrderEditViewModel 
{ 
    public int OrderId { get; set; } 

    public DateTime? ShippingDate { get; set; } 

    [StringLength(500)] 
    public string Remark { get; set; } 
    //... 

    public OrderEditCustomerViewModel Customer { get; set; } 
} 

public class OrderEditCustomerViewModel 
{ 
    [ReadOnly(true)] 
    public string Name { get; set; } 

    [ReadOnly(true)] 
    public string City { get; set; } 
    // ... 
} 

このOrderEditCustomerViewModelOrderEditViewModelへの参照を必要としません。

あなたがそうのように、このビューモデルを読み込むことができます。一方

var orderEditViewModel = context.Orders 
    .Where(o => o.OrderId == 5) 
    .Select(o => new OrderEditViewModel 
    { 
     OrderId = o.OrderId, 
     ShippingDate = o.ShippingDate, 
     Remark = o.Remark, 
     Customer = new OrderEditCustomerViewModel 
     { 
      Name = o.Customer.Name, 
      City = o.Customer.City 
     } 
    }) 
    .SingleOrDefault(); 

を、あなたが編集顧客情報を可能にし、リスト内の顧客の注文を表示するCustomerEditViewを持っている場合は、ViewModelには次のようになります。ここで

public class CustomerEditViewModel 
{ 
    public int CustomerId { get; set; } 

    [Required, StringLength(50)] 
    public string Name { get; set; } 

    [Required, StringLength(50)] 
    public string City { get; set; } 
    //... 

    public IEnumerable<CustomerEditOrderViewModel> Orders { get; set; } 
} 

public class CustomerEditOrderViewModel 
{ 
    [ReadOnly(true)] 
    public DateTime? ShippingDate { get; set; } 

    [ReadOnly(true)] 
    public string Remark { get; set; } 
    // ... 
} 

CustomerEditOrderViewModelCustomerEditViewModelへの参照を必要としない、あなたは、たとえば、データベースからこの方法をViewModelにを作成することができます。

var customerEditViewModel = context.Customers 
    .Where(c => c.CustomerId == 8) 
    .Select(c => new CustomerEditViewModel 
    { 
     CustomerId = c.CustomerId, 
     Name = c.Name, 
     City = c.City, 
     Orders = c.Orders.Select(o => new CustomerEditOrderViewModel 
     { 
      ShippingDate = o.ShippingDate, 
      Remark = o.Remark 
     }) 
    }) 
    .SingleOrDefault(); 

Customer(*)ViewModelOrder(*)ViewModelは、使用されるビューに応じて、必要な参照、プロパティ、およびデータ注釈に関して異なります。

これらの考慮事項を念頭に置いて、OrderViewModelCustomerViewModelとの間の相互の正しい参照に関する質問は、通常、ビューに対してこのような双方向参照が必要ないため消えます。

+0

Slauma .. viewmodelとEFエンティティとのマッピングをどのようにしますかおよびその逆? – user384080

+0

また、どうやってパブリックにIEnumerable Order {get;セット; } CustomerEditViewModelで?あなたは怠惰か熱心ですか? – user384080

+0

@ user384080:EFエンティティからViewModelへのマッピングは、「選択」という2つのコードスニペットです(これは「投影」と呼ばれ、遅延や熱心な読み込みではありませんが、 ViewModelには本当に必要です。不必要なオーバーヘッドとなる完全なエンティティではありません)。特に、最後のスニペットは 'Orders'コレクションにも挿入されます(内側の' Select'を参照)。 ViewModelからDTOを使用するエンティティに戻すには、ViewModelのプロパティをDTOに手動でマップするか、AutoMapperのようなツールを使用します。 – Slauma

関連する問題