2013-02-06 11 views
15

Chciałbym znaleźć sposób użycia Linq do filtrowania właściwości nawigacji do podzbioru powiązanych obiektów. Znam wszystkie odpowiedzi wokół tej kwestii proponuję robić anonimowy wyboru takich jak:EntityFramework 5 filtruj zawartą właściwość nawigacji

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

Jest to jednak znacznie mniej niż idealne ze względu na ogólny charakter naszego pokolenia zapytań, a także daje znacznie przerażające zapytań SQL jeśli zwymiotować profiler.

Chciałbym być w stanie osiągnąć coś takiego:

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

Zdaję sobie sprawę, że to nie jest obsługiwana w EF5 (lub dowolnej wersji dla tej sprawy), ale nie musi być drogą do osiągnięcia utwierdzania zestaw wyników przez Linq bez zagłębiania się w anonimowe instrukcje typu select.

próbowałem robić coś na melodię:

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

Jednak nie można mieć zadanie wewnątrz wyrażenia lambda i wybierając typ anonimowy tutaj powoduje ten sam dylemat, że nie używając select.

Chyba nie mogę pojąć dlaczego EF nie zapewnia sposób (że mogę znaleźć) do generowania:

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 

To jest tak proste, aby ograniczyć sprzężenia w SQL Musi być jakiś sposób, aby zrobić przez Linq.

PS: Mam wyszukiwane stos, MSDN, ekspertów wymiany, itp. Proszę zrozumieć, że to nie jest duplikat. Cokolwiek, nawet dotykając tego tematu, ma odpowiedź "Nie da się zrobić" lub nie ma żadnej odpowiedzi. Nic nie jest niemożliwe ... włącznie z tym.

+1

Oto odpowiedź "można zrobić": http://stackoverflow.com/a/13904825/861716 –

+5

Istnieją sposoby na rozszerzenie mechanizmu generowania zapytań w EF. Więc nie jest to niemożliwe, a jeśli jest to jedyna trasa, wówczas odpowiedź jest rozszerzeniem do silnika zapytań EF, aby umożliwić INNER/OUTER JOIN zawieranie dodatkowych filtrów. NIC NIE jest możliwe ... jeśli będę musiał ponownie skompilować EF, to ... Nie mam odpowiedzi, co oznacza, że ​​odpowiedź polega na samodzielnym jej budowaniu (którą obecnie, a nawet kiedy zadałem pytanie, zaplanowałem) – VulgarBinary

+4

To jest duch!! –

Odpowiedz

8

Cokolwiek, nawet dotykając tego tematu, ma wyzwolenie: "Nie można wykonać" nie można odpowiedzieć ani odpowiedzieć ". Nic nie jest niemożliwe ... w tym.

Pewnie. To jest możliwe. Możesz pobrać kod źródłowy EF i dodać tę funkcję samodzielnie. Będzie to wielki wkład w projekt open source i społeczność. Wierzę, że zespół EF chętnie pomoże Wam w wysiłkach.

W obecnej wersji "nie można tego zrobić" is the answer. Możesz użyć rzutowania do anonimowego lub specjalnego typu niezmapowanego, jak opisałeś na początku pytania. Inne opcje to osobne jawne zapytanie, które ładuje powiązane jednostki dla pojedynczego nadrzędnego lub osobnego zapytania, aby załadować powiązane jednostki dla wszystkich rodziców.

stosunki obciążenia dla pojedynczego rodzica:

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

stosunki obciążenia dla wszystkich rodziców (wymaga leniwy załadunku być wyłączone):

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

Drugie rozwiązanie wymaga dziecko, aby mieć właściwości nawigacji z powrotem do rodzic (do skonstruowania tego samego warunku zapytania używanego początkowo do ładowania rodzica).Jeśli wszystko jest poprawnie skonfigurowane i podłączone są encje, EF powinno automatycznie naprawić relacje (kolekcje) w elementach nadrzędnych (ale nie będzie oznaczać kolekcji w dynamicznym proxy jako załadowany, dlatego nie można tego używać razem z leniwym ładowaniem).

+0

to podobno przedłużam rdzeń EF5. Czy wiesz, czy istnieje sposób na rozszerzenie zamiast modyfikowania i ponownej kompilacji całej biblioteki DLL? – VulgarBinary

+1

Będziesz musiał ponownie skompilować bibliotekę DLL. Możesz odwiedzić stronę [EF codeplex EF] (http://entityframework.codeplex.com/discussions) i omówić ten wkład bezpośrednio z zespołem EF - mogą mieć już projekt wysokiego poziomu dla tej funkcji i udostępnić go Tobie. –

+3

Głosuj na filtrowanie Dołącz [tutaj] (https://entityframework.codeplex.com/workitem/47)! – Chris

Powiązane problemy