2013-05-16 19 views
7

現在、N層Webプロジェクトを作成中です。データ転送オブジェクトとその利点を研究した後、私たちはこのパターンに一歩を踏み出すことにしました。私たちのASP.NET MVC WebサイトはEF DbContextに直接アクセスすることはできませんが、DTOを使用してエンティティデータを送受信します。 DTOとエンティティモデルの間で変換するサービス/マッピングレイヤが存在します。Entity FrameworkモデルのナビゲーションプロパティをDTOに変換する

私の質問は、エンティティモデルのナビゲーションプロパティをDTOに変換する最良の方法は何ですか?以下は

プロジェクトからのエンティティモデルとそのDTOの例である:

エンティティモデル:

public class Payment 
{ 
    public int ID { get; set; } 
    public DateTime? PaidOn { get; set; } 
    public decimal Amount { get; set; } 
    public string Reference { get; set; } 

    //Navigation Properties 
    public virtual PaymentMechanism PaymentMechanism { get; set; } 
    public virtual ICollection<Order> Orders { get; set; } 
} 

DTO:

public class PaymentDto 
{ 
    public int ID { get; set; } 
    public DateTime? PaidOn { get; set; } 
    public decimal Amount { get; set; } 
    public string Reference { get; set; } 

    //--------Navigation Properties - Object Ids-------- 
    public int PaymentMechanismId { get; set; } 
    public ICollection<int> OrderIds { get; set; } 
} 

見ることができるようにそれらはナビゲーションプロパティを除いて非常に似ています。エンティティモデルの代わりに(エンティティの)整数IDを保持するように変更しました。したがって、ナビゲーションプロパティエンティティを取得する必要がある場合、そのIDは、データベースからエンティティを取得し、DTOにマップしてコレクションを返すサービス/マッピングレイヤ関数に渡すことができます。これは容認できる方法でしょうか?

私はこの分野に新しいので、私の用語のいくつかは完全に正しいとは言えないかもしれませんが、うまくいけば私は何を得ているのか理解できます。私が何かの詳細を明確にしたり追加したりする必要がある場合は、私に知らせてください。

答えて

12

あなたは、投影を使用してのDTOをロードすることができます。

var paymentDtos = context.Payments 
    .Where(p => p.Amount >= 1000m) // just an example filter 
    .Select(p => new PaymentDto 
    { 
     ID = p.ID, 
     PaidOn = p.PaidOn, 
     Amount = p.Amount, 
     Reference = p.Reference, 
     PaymentMechanismId = p.PaymentMechanism.ID, 
     OrderIds = p.Orders.Select(o => o.ID) 
    }) 
    .ToList(); 

あなたはこのコンパイルをしないようにICollection<int>として、しかしIEnumerable<int>としてDTOにOrderIdsを宣言しなければなりません。

このキーコレクションが本当に便利かどうかはわかりません。あなたが注文をロードしたい場合は、後であなたはそうのように、ちょうどPaymentIDに基づいて個別のサービス方法でそれを行うことができます:あなたの答えのための

public IEnumerable<OrderDto> GetPaymentOrders(int paymentID) 
{ 
    return context.Payments 
     .Where(p => p.ID == paymentID) 
     .Select(p => p.Orders.Select(o => new OrderDto 
     { 
      ID = o.ID, 
      //etc. mapping of more Order properties 
     })) 
     .SingleOrDefault(); 
} 
+0

おかげで、私はあなたの時間を感謝しています。私はあなたに最高の投票を与えるだろうが、私は十分な担当者を持っていない! この投影法の例は、AutoMapperのようなマッピングライブラリとどう違うのですか? 私はキーコレクションについて何を意味しているか正確に知っていますが、エンティティリレーションシップの参照を保持する方法です。私はそれが必ずしも必要ではないと思うが、それはいくつかのDTOにとって有益であると証明できる。 –

+0

@ChrisWhite:AutoMapperを使用すると、DBからすべてのOrdersを含む 'Payment'エンティティを最初にロードし、AutoMapperを適用して、ロードされたプロパティのほとんどを無視します。 'int'のみを含んでいます。これは多くのクエリのオーバーヘッドになる可能性があります。上記の投影はデータベース内で完全に実行され、投影で要求された列のみを返します。 – Slauma

関連する問題