2016-07-05 84 views
5

Sfondo

ho bisogno di essere in grado di costruire un .include che filtra i risultati fino al record creati durante o prima di una data specifica. Non conoscerò i tipi di oggetti nell'istruzione LINQ originale e li troverò (attraverso un sacco di cerchi, ma funziona).creare dinamicamente Includere con Dove Filtro

Ho un grafo di oggetti come questo:

  A -> Ac 
     /\ 
    Bc <- B \ 
    / \ 
Cc <- C  D -> Dc 

oggetti Ac, Bc, Cc e Dc si trovano tutti in modo dinamico (cioè, uno sviluppatore non digitare queste relazioni quando si scrive il LINQ originale dichiarazione). Questi devono quindi essere aggiunti a un'espressione IQueryable e restituiscono solo i valori fino a un DateTime specifico.

Il Codice So Far

ho provato la costruzione di una funzione che costruisce un lambda e mette a confronto le date. Finora, se la query originale è A.Include(x => x.B).Include(x => x.B.Select(y => y.C), posso creare la stringa "A.B.Bc", quindi conosco i tipi di A, B e Bc e il loro modo di rapportarsi.

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

Il problema è che il codice di cui sopra si blocca a causa "A.B.Bc.CreatedUtc" non è il modo corretto di caricare la proprietà data - ho bisogno di attraversare questo attraverso .Select dichiarazioni.

Il problema

Per entrambi carico gli atti e filtro loro, devono costruire dinamicamente un .Select per staccare i valori ho bisogno (che, fortunatamente, sono statica su eredità) e inserire quei valori in un tipo anonimo, che può essere filtrato con un .Where(). Tutto ciò deve essere fatto con generici minimi, in quanto non ho tipi di compilazione in fase di validazione e dovrei abusare della riflessione per farli funzionare.

In sostanza, ho bisogno di creare questa:

.Select(x => new 
{ 
    Bc = x.B.Select(z => z.Bc.Select(y => y.CreatedUtc).Where(q => q > DateTime.UtcNow)), 
    A= x 
}) 

in modo dinamico, utilizzando la stringa "A.B.Bc", per qualsiasi livello di nidificazione.

Risorse

Questo è dove ho visto come filtrare un EF includono metodo: LINQ To Entities Include + Where Method

Questo post parla di creazione dinamica di una selezione, ma si sta selezionando solo i valori di alto livello e non sembra come si può costruire il resto delle parti necessarie per il mio problema: How to create LINQ Expression Tree to select an anonymous type

dinamica LINQ

Utilizzando la System.Linq.libreria dinamica, ho cercato di accedere al valore CreatedUtc off di Bc:

query = (IQueryable<T>) query.Select(includeString + ".CreatedUtc"); 

Dove includeString = "B.Bc", ma questo mi dà un'eccezione di:

Exception thrown: 'System.Linq.Dynamic.ParseException' in System.Linq.Dynamic.dll 

Additional information: No property or field 'Bc' exists in type 'List`1' 

risposta

2

Credo System.Linq.Dynamic è quello che ti serve. Si tratta di una libreria in origine scritto da ScottGu da Microsoft, e permette di costruire query LINQ da stringa del genere:

IQueryable nestedQuery = query.Select("B.Bc.CreatedUtc"); 

dove query è IQueryable<A>.

C'è un numero di fork di questa libreria. È possibile iniziare da here. La documentazione sul linguaggio di query è here. Anche here c'è una versione con alcune funzionalità aggiuntive e la versione here è dotnet.core.

UPD1: This libreria manca del metodo di estensione SelectMany ma this uno ha. Quindi, con questi ultimi biblioteca è possibile effettuare le seguenti operazioni:

query.SelectMany("B").SelectMany("Bc").Select("CreatedUtc"); 
+0

Quando includo la stringa ' "B.Bc.CreatedUtc"', ottengo questo errore: 'Informazioni aggiuntive: No proprietà o il campo 'Bc' esiste nel tipo 'List'1''. Non sembra che stia esplorando correttamente i grafici annidati? – Max

+0

Puoi mostrare altro codice qui? –

+0

Ho aggiornato il mio post principale. – Max

Problemi correlati