Tło
muszę być w stanie zbudować .Include że filtry Wyników dół do rejestrów utworzonych na lub przed określoną datą. Nie znam typów obiektów na oryginalnym wyciągu LINQ i znajdę je (przez całą masę obręczy, ale to działa).dynamicznego tworzenia Dołącz z Gdzie Filtr
Mam wykres obiektów tak:
A -> Ac
/\
Bc <- B \
/ \
Cc <- C D -> Dc
Obiekty Ac
, Bc
, Cc
, a wszystko Dc
znajdują się dynamicznie (to jest deweloper nie wpisać w te relacje pisząc oryginalny LINQ komunikat). Następnie należy je dodać do wyrażenia IQueryable i zwracać wartości tylko do określonego obiektu DateTime.
Kodeks So Far
próbowałem budowania funkcji, które konstruuje lambda i porównuje dat. Do tej pory, jeśli oryginalne zapytanie to A.Include(x => x.B).Include(x => x.B.Select(y => y.C)
, mogę skonstruować ciąg "A.B.Bc"
, więc znam typy A, B i Bc oraz sposób, w jaki się one odnoszą.
private static IQueryable<T> FilterChangeTrackerToDate<T>(this IQueryable<T> query, string includeString, DateTime targetDateTime)
{
var param = Expression.Parameter(typeof(T), "x");
var prop = Expression.Property(param, includeString + ".CreatedUtc");
var dateConst = Expression.Constant(targetDateTime);
var compare = Expression.LessThanOrEqual(prop, dateConst);
var lambda = Expression.Lambda<Func<T, bool>>(compare, param);
return query.Where(lambda);
}
Problem jest, że powyższy kod wywala bo "A.B.Bc.CreatedUtc"
nie jest poprawny sposób, aby załadować właściwość data - muszę przechodzić przez to .Select
wypowiedzi.
Problem
W celu zarówno obciążenie zapisy i filtr im, muszę dynamicznie zbudować .Select
wyciągnąć wartości potrzebne (które, na szczęście, są statyczne na podstawie dziedziczenia) i umieść te wartości w anonimowym typie, który można następnie przefiltrować za pomocą .Where()
. Wszystko to musi być zrobione przy minimalnym poziomie generycznym, ponieważ nie mam typów kompilacji do sprawdzenia i musiałem nadużywać refleksji, aby je uruchomić.
Zasadniczo trzeba utworzyć w ten sposób:
.Select(x => new
{
Bc = x.B.Select(z => z.Bc.Select(y => y.CreatedUtc).Where(q => q > DateTime.UtcNow)),
A= x
})
dynamicznie przy użyciu ciąg "A.B.Bc", na dowolnym poziomie zagnieżdżenia.
Resources
To gdzie ja zobaczyłem jak filtrować EF obejmują metody: LINQ To Entities Include + Where Method
Ten post mówi o dynamicznie tworząc Select, ale to jest wybór tylko wartości najwyższego poziomu i nie wydaje jak można go zbudować resztę części potrzebnych do mojego problemu: How to create LINQ Expression Tree to select an anonymous type
dynamiczne Linq
Używanie System.Linq.Dynamiczne biblioteki, starałem się uzyskać dostęp do wartości CreatedUtc
off BC:
query = (IQueryable<T>) query.Select(includeString + ".CreatedUtc");
Gdzie includeString = "B.Bc"
, ale to daje mi wyjątek:
Exception thrown: 'System.Linq.Dynamic.ParseException' in System.Linq.Dynamic.dll
Additional information: No property or field 'Bc' exists in type 'List`1'
Kiedy to ciąg '„B.Bc.CreatedUtc”', otrzymuję ten błąd: 'Informacje dodatkowe: Nie istnieje nieruchomości lub pole„Bc”w typie "Lista" 1 ". Wygląda na to, że nie zagląda poprawnie do zagnieżdżonych wykresów? – Max
Czy możesz pokazać tutaj więcej kodu? –
Zaktualizowałem mój główny wpis. – Max