2013-05-16 9 views
7

Ich arbeite derzeit an einem n-Tier-Web-Projekt. Nachdem wir uns mit den Datenübertragungsobjekten und ihren Vorteilen beschäftigt haben, haben wir uns entschieden, dieses Muster zu testen. Unsere ASP.NET MVC-Website hat keinen direkten Zugriff auf den EF DbContext, sondern verwendet stattdessen DTOs zum Senden und Empfangen von Entitätsdaten. Es wird eine Service-/Mapping-Schicht geben, die zwischen DTOs und Entitätsmodellen konvertiert.Übersetzen von Entity Framework-Modell Navigationseigenschaften in DTOs

Meine Frage ist, was ist die beste Möglichkeit, Entity-Modell Navigationseigenschaften in seine DTO zu übersetzen?

Unten ist ein Beispiel eines Entity-Modell und seine DTO aus dem Projekt:

Entity Model:

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

Wie man sehen kann Sie sind sehr ähnlich mit Ausnahme der Navigationseigenschaften. Ich habe sie geändert, um ganzzahlige Ids (der Entitäten) anstelle der Entitätsmodelle zu halten. Wenn daher die Navigationseigenschaftsentitäten abgerufen werden müssen, können ihre Ids in eine Dienst-/Zuordnungsschichtfunktion übergeben werden, die die Entitäten aus der Datenbank abruft, sie den DTOs zuordnet und die Sammlung zurückgibt. Ist das ein akzeptabler Weg, Dinge zu tun?

Ich bin neu in diesem Bereich, so dass einige meiner Terminologie möglicherweise nicht völlig korrekt sind, aber hoffentlich werden Sie verstehen, worauf ich hinaus will. Wenn Sie mich bitten, weitere Einzelheiten zu klären oder zu erläutern, lassen Sie es mich bitte wissen.

Antwort

12

Sie können die DTOs laden eine Projektion:

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

Sie haben die OrderIds im dto als IEnumerable<int> allerdings zu erklären, nicht als ICollection<int> diese Kompilierung zu machen.

Ich bin mir nicht sicher, ob diese Schlüsselsammlung wirklich nützlich ist. Wenn Sie die Aufträge zu ladende später könnte es in einer separaten Service-Methode tun basierte nur auf den ID der Payment, etwa so:

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

Vielen Dank für Ihre Antwort, ich Ihre Zeit zu schätzen wissen. Ich würde Ihnen eine Stimme geben, aber ich habe nicht genug Rep! Wie unterscheidet sich dieses Projektionsbeispiel von einer Zuordnungsbibliothek wie AutoMapper? Ich weiß genau, was Sie über die Schlüsselsammlungen meinen, aber es ist eine Möglichkeit, einen Verweis auf Entitätsbeziehungen beizubehalten. Ich nehme an, es ist nicht immer notwendig, aber es könnte für einige DTOs nützlich sein. –

+0

@ChrisWhite: Wenn Sie AutoMapper verwenden, werden Sie gezwungen, zunächst die Entität "Zahlung" mit allen "Bestellungen" aus der DB (mit allen Spalten der Reihenfolge) zu laden und anschließend den AutoMapper anzuwenden, der die meisten geladenen Eigenschaften wegen Ihrer Sammlung im Dto ignoriert enthält nur ein 'int'. Dies könnte eine Menge an Abfrageaufwand bedeuten. Die obige Projektion wird vollständig in der Datenbank ausgeführt und gibt nur die in der Projektion angeforderten Spalten zurück. – Slauma