5

Sto utilizzando Entity Framework 4.3.1 con un approccio Code First. Inoltre, sto usando LinqKit per usare PredicateBuilder.Codice quadro entità Primo 4.3/predicato LINQKit per la tabella correlata

Se ho le tabelle in questo modo:

posizione, il fuso orario (Many: 1)

..e vorrei avere qualcosa in questo modo:

Expression<Func<TimeZone, bool>> pred = PredicateBuilder.True<TimeZone>(); 
pred = pred.And(tz => tz.TimeZoneCode == "EST"); 

List<Location> locations = context.Locations 
    .AsExpandable().Where(pred) 
    .Select(loc => loc).ToList(); 

Questo non funziona, perché il predicato è costruito per accettare un fuso orario, ma il metodo Where() riceve una posizione.

posso riscrivere il predicato in questo modo, ma io non voglio, perché voglio avere una fabbrica predicato che crea predicati per tipi specifici (io non voglio usare le proprietà Navigator in questo modo):

Quale sintassi è possibile utilizzare (se presente) per utilizzare il predicato come costruito nel primo esempio, dove prende un TimeZone, piuttosto che farlo prendere una posizione e percorrere l'albero tramite le proprietà di navigazione (poiché questo è meno riutilizzabile). Sarebbe bello se ci fosse un modo per sfruttare la conoscenza che EF ha delle proprietà di navigazione, in primo luogo, ed essere in grado di utilizzare un predicato per il tipo di proprietà di navigazione.

risposta

4

Dopo circa una settimana di difficoltà, ho scoperto che in realtà è possibile farlo. I passi sono:

  1. Definire un predicato che è la query per la vostra proprietà interno (subPredicate)
  2. Invoke che subPredicate da un altro predicato (predicate), contro la proprietà dell'oggetto padre.
  3. Expand il tuo predicate quando lo si utilizza nella clausola Where.

Ecco il codice rivisto per il tuo esempio:

var subPredicate = PredicateBuilder.True<TimeZone>(); 
subPredicate = subPredicate.And(tz => tz.TimeZoneCode == "EST"); 

var predicate = PredicateBuilder.True<Location>(); 
predicate = predicate.And(l => subPredicate.Invoke(l.TimeZone)); 

List<Location> locations = context.Locations 
    .AsExpandable().Where(pred.Expand()) 
    .Select(loc => loc).ToList(); 
+0

grazie per l'aggiornamento! Puoi aggiungere informazioni sul fatto che questo predicato sia applicato sul lato server, tramite LINQ/LINQKit che alimenta EF qualcosa che può tradurre in SQL, oppure questa forza bruta applicata internamente in EF su un set di dati non filtrato? –

+0

@PittsburghDBA si ottiene una chiamata al DB tramite EF, che si traduce in SQL. – Grinn

+0

Grazie per questo straordinario seguito !!!!! –

1

Solo per aggiornare questo: si scopre che l'intento di questi tipi di predicati è quello di filtrare l'entità primaria. Il concetto mentale è: decidere quali entità si desidera restituire e restituirle. EF non è apparentemente progettato per questo tipo di deep predicate application su entità child.

Una persona (non ricordo dove) ha fatto un ottimo punto: se i bambini erano precaricati, non ci si aspetterebbe una collezione parzialmente caricata. Pertanto, non avrebbe senso avere un'entità Fattura, ad esempio, ma solo metà delle linee della fattura.

Quello che volevo ottenere era più lungo la linea di EXISTS() o IN(), dove si poteva dire "Dammi tutte le fatture dove ci sono linee di fatturazione per i tipi di prodotto 'Dadi' e 'Bulloni'". Questo è fattibile, ma potresti dover applicare LINQ o comporre il tuo oggetto. L'intento di EF out of the box è di consegnarti la fattura, quindi puoi caricare le linee della fattura in modo pigramente o avido, ma non utilizzarle come filtro direttamente dal database.

Ci sono alcuni costrutti che ho visto per realizzare qualcosa di simile, ma la sintassi diventa molto ingestibile molto rapidamente.

Non combattere il municipio.

+0

Sono in questo scenario ... dopo un sacco di lettura e di tentativi ed errori di codifica ho anche learn't non combattere il sistema, altrimenti si ottiene codice complesso e brutto. Ugh !!! EF & PredicateBuilder è/sono valido per le opere delle entità primarie. Cosa hai fatto per quanto riguarda le entità nidificate? Sono a un bivio ora, decidendo cosa fare dopo. (Capisco che sono passati 2 anni dalla tua risposta). –

+0

Abbiamo abbandonato EF e ora utilizziamo SQLClient. Nessuna di queste piattaforme ORM può competere con ADO.Net in termini di prestazioni non elaborate, non preoccupatevi di questi problemi. –

+0

@ThomasVeil dai un'occhiata alle brutali differenze delineate qui: https://web.archive.org/web/20131205132904/http://ormbattle.net/ –

Problemi correlati