3

Ich arbeite an einem Modell mit zwei Klassen: Product und Transaction.Wie lade ich bestimmte Felder eines Kindobjekts nur in Entity Framework 6.1?

Wie mache ich eine Abfrage, die ein Produkt und das Datum seiner Transaktionen abrufen wird? Ich habe versucht, so etwas wie

var product = db.Products.Include(p => p.Transactions.Select(t => new { t.Date })).Where(p => p.ProductId = productId); 

Aber es gibt eine Ausnahme aus:

Der Ausdruck Include Pfad zu einer Navigationseigenschaft von der Art definiert beziehen. Verwenden gepunktete Wege für eine Referenz Navigation Eigenschaften und den Select-Operators für die Sammlung Navigation Eigenschaften

Bearbeiten zur Klarstellung: Was ich will, erreichen, ist eigentlich nicht Laden TransactionId und Customer wenn Transaction geladen wird. versuchen

+0

können Sie nicht „nicht geladen werden“ 'TransactionId' und' Kunden, weil sie bereits geladen wurden, da sie keine Navigationseigenschaften sind. Und selbst du konntest das tun, du würdest keinen Nutzen daraus ziehen ... – haim770

Antwort

4

Um das zu erreichen, was Sie brauchen Sie nicht andere Wahl haben, als Sie Ihre Anfrage an einen anonymen Typ oder ein DTO projizieren. Wie Sie sehen können, können Sie in der Erweiterungsmethode Include einfach die verknüpften Entitäten angeben, die Sie laden möchten und die in einem inneren Join mit einer Tabelle (oder mehreren Joins, siehe Abschnitt im zitierten Link) übersetzt werden Das bedeutet nicht, dass Sie alle Eigenschaften aus den zugehörigen Entitäten laden. Wenn Sie die Methode Select aufrufen, können Sie auswählen, welche Spalten Sie projizieren möchten, aber Sie können keine Linq-zu-Entitäten-Abfrage mit einem Entitätstyp projizieren. Sie müssen eine der beiden Optionen verwenden, die ich oben kommentiert habe. So ist mein Rat in Ihrer Business-Logik-Schicht eine Reihe von Klassen (DTOs) schafft das Ergebnis Ihrer Anfragen zu projizieren, zB:

public class ProductDTO 
{ 
    [DataMember] 
    public Guid ProductId {get; set;} 
    [DataMember] 
    public virtual IEnumerable<DateTime> TransactionDates { get; set; } 
} 

Später können Sie etwas tun:

var product = db.Products.Where(p => p.ProductId = productId) 
         .Select(pr=> new ProductDTO 
         { 
          ProductId = pr.ProductId, 
          TransactionDates = pr.Transactions.Select(tr=>tr.Date), 
         }.ToList(); 

Siehe ich muss Include Erweiterungsmethode in diesem Fall nicht aufrufen, da ich in Select eine Spalte von Transactions Tabelle projiziere. An diesem Punkt sind die Daten noch nicht geladen, Sie definieren nur eine linq-Abfrage, die später in sql übersetzt wird. Wenn das stattfindet ?, wenn Sie ToList Erweiterungsmethode aufrufen.

Als letzte Empfehlung empfehle ich Ihnen, einen Blick auf Automapper zu werfen. Sobald Sie Ihre Einheiten mit ihren jeweiligen DTOs zugeordnet haben, können Sie Ihre Abfragen so sein:

var product = db.Products.Where(p => p.ProductId == productId) 
         .ProjectTo<ProductDTO>()  
         .ToList(); 

Weitere Daten zu ProjectTo Extension-Methode in diesem link

1

könnten Sie auch Anonymous projection

var product = db.Products.Where(p => p.ProductId = productId) 
         .Select(pr=> new 
         { 
          product = pr, 
          transactionDates = pr.Transactions.Select(tr=>tr.Date), 
         }.ToList(); 
Verwandte Themen