2013-02-06 6 views
15

Ich möchte einen Weg finden, Linq verwenden, um eine Navigationseigenschaft zu einer Teilmenge von verbundenen Entitäten zu filtern. Ich weiß, dass alle Antworten, um dieses Thema empfehlen, einen anonymen Wähler tun wie:EntityFramework 5 Filter eine eingeschlossene Navigationseigenschaft

query.Where(x => x.Users.Any(y => y.ID == actingUser.ID)) 
    .Select(x => new 
    { 
     Event = x, 
     Discussions = x.Discussions.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>()) 
    }) 
    .OrderBy(x => x.Discussions.Count()) 
    .ThenBy(x => x.Event.Name); 

Dies ist jedoch deutlich geringer als ideal aufgrund der allgemeinen Natur unserer Abfrage Generation und ergibt auch deutlich schreckliche SQL-Abfragen, wenn Sie erbrechen Profiler.

Ich möchte in der Lage sein, etwas zu erreichen, wie:

query.Include(x => x.Discussions.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>())) 
     .OrderBy(x => x.Discussions.Count()) 
     .ThenBy(x => x.Name); 

Mir ist klar, dass dies nicht in EF5 (oder einem beliebigen Version für diese Angelegenheit) unterstützt wird, aber es muss ein Weg, um das erreichen Zwang Ergebnis wird über Linq festgelegt, ohne sich in anonyme Select-Anweisungen zu vertiefen.

Ich habe etwas in der Größenordnung versuchter tun:

query.GroupJoin(discquqery, 
    x => x.ID, 
    x => x.Event.ID, 
    (evt, disc) => evt.Discussions = disc.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>())).ToList(); 

jedoch nicht Zuordnung in einem Lambda-Ausdruck haben kann und die Auswahl eines anonymen Typ hier bewirkt, dass das gleiche Dilemma, dass sie die select nicht verwenden.

Ich glaube, ich kann nicht begreifen, warum EF nicht bieten eine Möglichkeit, (dass ich finden kann) zu erzeugen:

SELECT 
    --Properties 
FROM Event e 
LEFT OUTER JOIN Discussions d 
    ON e.ID = d.EventID AND --Additional constraints 
WHERE 
    --Where conditions 
ORDER BY 
    --Order Conditions 

Es ist so einfach, die Verbindung in SQL zu beschränken muss es einen Weg, um zu tun, es auch durch Linq.

PS: Ich habe Stack, MSDN, Expertenaustausch usw. gesucht. Bitte beachten Sie, dass dies kein Duplikat ist. Alles, was dieses Thema berührt, hat entweder eine Antwort "Es kann nicht getan werden" oder überhaupt keine Antwort. Nichts ist unmöglich ... einschließlich dies.

+1

Nun, hier ist eine Antwort "es kann getan werden": http://StackOverflow.com/a/13904825/861716 –

+5

Es gibt Möglichkeiten, die Abfragegenerierungsengine in EF zu erweitern. Es ist also nicht unmöglich, und wenn das der einzige Weg ist, dann ist die Antwort die Erweiterung der EF-Abfrage-Engine, damit INNER/OUTER JOIN zusätzliche Filter enthalten kann. NICHTS ist unmöglich ... wenn ich EF neu kompilieren muss, dann werde ich ... Es hat keine existierende Antwort bedeutet, dass die Antwort es selbst erstellt (was ich momentan und sogar wenn ich die Frage stelle, geplant) – VulgarBinary

+4

Das ist das Geist!! –

Antwort

8

Alles, das sogar zu diesem Thema berührt, hat entweder eine Antwort "Es kann nicht getan werden" Antwort oder überhaupt keine Antwort. Nichts ist unmöglich ... einschließlich dieses.

Sicher. Es ist möglich. Sie können den EF-Quellcode herunterladen und diese Funktion selbst hinzufügen. Es wird ein großer Beitrag zum Open-Source-Projekt und der Community sein. Ich glaube, das EF-Team hilft Ihnen gerne bei Ihren Bemühungen.

Mit der aktuellen Version "es kann nicht getan werden" is the answer. Sie können die Projektion entweder als anonymen oder speziellen nicht zugeordneten Typ verwenden, wie Sie am Anfang Ihrer Frage beschrieben haben. Andere Optionen sind eine separate explizite Abfrage zum Laden verwandter Entitäten für ein einzelnes Elternteil oder eine separate Abfrage zum Laden verwandter Entitäten für alle Eltern.

Last Beziehungen für Alleinerziehende:

context.Entry(event) 
     .Collection(e => e.Discussions) 
     .Query() 
     .Where(d => ...) 
     .Load(); 

Last Beziehungen für alle Eltern (erfordert verzögertes Laden ausgeschaltet werden):

// load all parents 
var events = query.Where(e => ...).ToList(); 

// load child filtered by same condition for parents and new condition for children 
childQuery.Where(d => e.Event ... && d.Something ...).Load(); 

Die zweite Lösung Kind Navigationseigenschaft erfordert haben zurück zu Parent (zum Konstruieren der gleichen Abfragebedingung, die anfangs zum Laden von Parent verwendet wurde).Wenn Sie alles korrekt konfiguriert haben und Entitäten angefügt sind, sollte EF Ihre Relationen (Sammlungen) automatisch in übergeordneten Entitäten fixieren (aber es wird nicht die Sammlung in dynamischem Proxy als geladen markieren, so dass Sie dies nicht zusammen mit lazy loading verwenden können).

+0

dann erweitere ich anscheinend den EF5 Core. Wissen Sie, ob es eine Möglichkeit gibt, die gesamte DLL zu erweitern statt sie zu ändern und neu zu kompilieren? – VulgarBinary

+1

Sie müssen die DLL neu kompilieren. Sie können [EF-Codeplex-Site] (http://entityframework.codeplex.com/discussions) besuchen und diesen Beitrag direkt mit dem EF-Team besprechen - sie haben vielleicht bereits ein hochwertiges Design für dieses Feature und teilen es mit Ihnen. –

+3

Vote für gefilterte Include [hier] (https://entityframework.codeplex.com/workitem/47)! – Chris

Verwandte Themen