8

Qui è la mia espressione:EF Lambda: L'espressione Includere percorso deve fare riferimento a una proprietà di navigazione

Course course = db.Courses 
    .Include(
    i => i.Modules.Where(m => m.IsDeleted == false) 
     .Select(s => s.Chapters.Where(c => c.IsDeleted == false)) 
).Include(i => i.Lab).Single(x => x.Id == id); 

So che la causa è Where(m => m.IsDeleted == false) nella porzione moduli, ma perché lo fa causare l'errore? Ancora più importante, come posso risolverlo?

Se rimuovo la clausola where funziona correttamente ma voglio filtrare i moduli cancellati.

risposta

11

.Include viene utilizzato per caricare avidamente le entità correlate dal db. Cioè nel tuo caso assicurati che i dati relativi a moduli e laboratori siano caricati con il corso.

L'espressione di lamba all'interno di .Include deve indicare a Entity Framework quale tabella correlata includere.

Nel tuo caso stai anche provando a eseguire una condizione all'interno dell'inserimento, motivo per cui ricevi un errore.

Sembra che la tua domanda è questa:

trovare il corso che corrispondono a un dato id, con il relativo modulo ed laboratorio. Finché il modulo e il capitolo corrispondenti non vengono cancellati.

Se questo è giusto, allora questo dovrebbe funzionare:

Course course = db.Courses.Include(c => c.Modules) 
          .Include(c => c.Lab) 
          .Single(c => c.Id == id && 
             !c.Module.IsDeleted && 
             !c.Chapter.IsDeleted); 
+3

Questo è veramente sbagliato. Recupererai tutti gli articoli dalle tabelle Modules e Lab. –

3

ma perché lo fa causa l'errore?

Posso immaginare che a volte il team EF rimpiange il giorno in cui introducono questa sintassi Include. Le espressioni lambda suggeriscono che qualsiasi espressione linq valida può essere utilizzata per manipolare in modo subdolo il caricamento ansioso. Ma troppo male, non così. Come ho spiegato here, i lambda fungono solo da argomento stringa mascherato al sottostante metodo "reale" Include.

come si risolve?

migliore sarebbe quella di proiettare ad un'altra classe (per esempio, un DTO)

db.Courses.Select(x => new CourseDto { 
    Id = x.Id, 
    Lab = x.Lab, 
    Modules = x.Modules.Where(m => !m.IsDeleted).Select(m => new ModuleDto { 
     Moudle = m, 
     Chapters = x.Chapters.Where(c => c.IsDeleted) 
    } 
}).Single(x => x.Id == id); 

ma che può essere una modifica importante per voi.

Un'altra opzione è disabilitare il caricamento lazy e precaricare i moduli e i capitoli non eliminati del corso nel contesto dallo Load command. La correzione delle relazioni riempirà le giuste proprietà di navigazione. Il Include per Lab funzionerà normalmente.

A proposito, c'è uno change request per questa funzione.

Problemi correlati