2010-09-08 12 views
12

Ich benutze Entity Framework 4 mit MVC und muss sicherstellen, dass alle referenzierten Entitäten, die ich in meiner Ansicht verwenden möchte geladen wurden, bevor die Controller-Methode zurückgibt, andernfalls spuckt die Ansicht die gefürchteten aus:Entity Framework - Eager Loading verwandte Entitäten

Die ObjectContext-Instanz wurde entfernt und kann nicht mehr für Vorgänge verwendet werden, für die eine Verbindung erforderlich ist.

var sellers = context.Sellers.Include("Recommendations.User").ToList(); 

aber wenn ich (zum Beispiel) einen Helfer:

Wenn gerade aus dem Kontext der Auswahl, kann ich in der generierten SQL-Abfrage enthielt sie die Include(string) Methode zu zwingen, verwenden nur Methode, die eine Entität akzeptiert und alle zu ladenden Elemente benötigt, gibt es keine Include Methode zur Verfügung.

void Test(Seller seller) 
{ 
    // ensure all recommendations and their users are loaded 
} 

Die Brute-Force-Methode ist durch sie Schleife:

foreach (var recommendation in seller.Recommendations) 
    recommendation.User.ToString(); // just force a load 

Wenn ich 100 Empfehlungen haben, diese 101 SQL-Abfragen hinter den Kulissen zu schaffen. Idealerweise möchte ich eine Methode/Methode, die alle Recommendation AND User Objekte mit nur einer einzigen Reise nach SQL lädt.

Zeig mir das Geld.

EDIT Ich bin nicht wirklich interessiert zu diskutieren, ob dies eine gute oder schlechte Architektur ist. Ich habe mein Szenario für die Frage vereinfacht. Kannst du das machen, was ich mit der EF API frage?

EDIT 2

Ladislav's edit angeboten Hoffnung auf einen neuen Ansatz, aber es scheint, dass ich es nicht ganz bin.

kann ich erreichen, was ich über diese wollen:

context.Sellers.Include("Recommendations.User").Single(s => s.Id == seller.Id); 

Dieser Ansatz nicht LoadProperty ...

context.LoadProperty(seller, "Recommendations.User"); 

mit funktioniert ... wie es mit dem Fehler fehlschlägt ...

Die angegebene Navigationseigenschaft Recommendations.User konnte nicht gefunden werden.

Keine dieser Methoden funktioniert, wenn Sie keinen Bezug zum Kontext haben.

+0

Während dies Ihre Frage nicht beantwortet (daher poste ich es als Kommentar) - diskutiert es das Laden verwandter Entitäten, wie es derzeit in EF6 funktioniert. Dies ist auch der erste SOF-Link, der in Google auftaucht, wenn er nach "entity framework load related entities" sucht: http://msdn.microsoft.com/en-us/data/jj574232. Also dachte ich, ich würde teilen. –

Antwort

3

Ich denke, das ist ein Job für Ihr Repository, der in Ihrem Fall Methoden wie GetFullSeller (alle von Include geladenen Eigenschaften) und GetSeller (nur Basis-Entität) verfügbar machen sollte.

Edit:

Es gibt mehrere Möglichkeiten, wie Navigationseigenschaften in EF v4 zu laden.

Es gibt keinen automatischen Laden.

+1

bedeutet das, dass Sie immer nur an einem Objekt arbeiten würden, das direkt aus einem Repository stammt? Was wäre, wenn Sie eine Entität beispielsweise über WCF erhalten hätten, diese dann anhängen und weitere Felder auffüllen möchten, um weitere Transformationen durchzuführen, bevor Sie sie endgültig speichern? Jedenfalls sehe ich das nicht als eine Architekturfrage. Ich möchte nur wissen, ob die API dies unterstützt, und wenn nicht, warum nicht. –

0

Anstatt Ihre tatsächlichen Domänenobjekte (EntityObject s) an die Ansicht zu übergeben, möchten Sie vielleicht Ihren Controller verwenden, um sie einem Model-Objekt zuzuordnen, das besser darstellt, was Ihre Ansicht tatsächlich anzeigen sollte. Dies reduziert die Menge an Logik, die in Ihrer Ansicht benötigt wird, und hat den angenehmen Nebeneffekt, dass EntityObjects nach dem Ablauf ihres Kontextes nicht mehr weitergegeben werden.

bearbeiten basierend auf edit:

Nein, die API haben keine Möglichkeit, ein einzelnes Entity Objekt zu nehmen und jede andere Entitätsobjekt seiner Art zu machen, die es zur gleichen Zeit geladen wurde Lazy-bevölkert mit einer bestimmten Eigenschaft auf einen Schlag. Sie sind besser dran, alle Elemente an erster Stelle ziehen mit der Include Erwähnung, wie Sie in Ihrer Frage zeigen.

+0

danke für deine antwort. Ich habe meinen Fall aus Gründen der Klarheit in der Frage vereinfacht. Ich benutze tatsächlich ein "Ansichtsmodell", so dass meine Ansichten kaum logisch sind. Mein Modell ist eng mit Beziehungen verknüpft, und ich möchte diese Hierarchie nicht in Ansichtsmodellen neu erstellen. Daher habe ich ein Ansichtsmodell auf Basisebene mit einigen Entitätsaufzählungen. In meinem Fall muss ich eine andere Entität von denen in einer Aufzählung dereferenzieren. Dies ist keine Architekturfrage, sondern eher eine API-Frage. –

+0

basierend auf Ihrer Bearbeitung;) Das ist nicht ganz das, was ich tun möchte. Ich habe einen Verkäufer. Ich brauche alle Empfehlungen des Verkäufers geladen zu werden. Für jede dieser Empfehlungen muss der entsprechende Benutzer geladen werden. Ich brauche keine anderen Verkäufer geladen werden. –

+0

Wenn ich die API erfinden könnte, würde ich 'seller.Load (" Recommendations.User ")' sagen, genau wie ich in der ursprünglichen Entitätssatzabfrage (wie in OP.) –

2

Ich bin in der gleichen Situation. Ich denke, dass es mit EF sehr einfach ist, in ein 101-Abfrage-Problem zu fallen.

Eine Lösung kann sein, eine partielle Klasse Ihrer Seller-Klasse (generiert von EF) zu erstellen und einen GetSubclassNameQ, der ein IQueryable zurückgibt, und ein GetSubclassNameQFull, das ein IQueryable mit Eager-Laden zurückgibt, zu implementieren.

public partial class Seller{ 

    public IQueryable<Recommendation> GetRecommendationsQ(EntityContainer entitycontainer) { 
    return entitycontainer.Recommendations; 
    }  

    public IQueryable<Recommendation> GetRecommendationsQFull(EntityContainer entitycontainer) { 
    return this.GetRecommendationsQ(entitycontainer).Include("Recommendations.User"); 
    } 

    public IQueryable<Recommendation> GetRecommendationsQ() { 
    return GetRecommendationsQ(new EntityContainer()); 
    } 

    public IQueryable<Recommendation> GetRecommendationsQFull() { 
    return this.GetRecommendationsQ().Include("Recommendations.User"); 
    } 

} 
5

Dies ist eine alte Frage, aber in EF6 können Sie abhängige Objekte in einem Objekt wie this erreichen Laden:

context.Entry(seller).Collection(s => s.Recommendations).Query().Include(r => r.User)).Load(); 

, die für die gegebene seller

alle Recommendations und den damit verbundenen Users würde laden
Verwandte Themen