6

Modifica: Aggiornato descrizione del problema sulla base di test - 12 settembre 2011.EF4.1 entità nidificata multipla Include ottiene NotSupportedException?

Ho questa domanda che getta una NotSupportedException ogni volta che io chiamo ToList() ("il metodo specificato non è supportato.").

IQueryable<FileDefinition> query = db 
    .FileDefinitions 
    .Include(x => x.DefinitionChangeLogs) 
    .Include(x => x.FieldDefinitions.Select(y => y.DefinitionChangeLogs)) // bad 
    .Include(x => x.FieldDefinitions.Select(y => y.FieldValidationTables)) // bad 
    .Where(x => x.IsActive); 
List<FileDefinition> retval = query.ToList(); 

Se commento una riga che ho commentato come "cattiva", la query funziona. Ho anche provato a includere diverse entità nidificate nel mio modello a oggetti con lo stesso effetto. Includere qualsiasi 2 causerà un arresto anomalo. Per nested, intendo una proprietà di navigazione di una proprietà di navigazione. Ho anche provato a utilizzare i metodi .Include con un percorso stringa: stesso risultato.

mia struttura della tabella simile a questa:

Db model

Db model 2

Questo sta utilizzando MySQL 5.1 (tabelle InnoDB ovviamente) come l'archivio di database con MySQL Connector/NET 6.3.4.

Quindi la mia domanda è: perché questo non funziona?

Nota: riesco a farlo funzionare se carico esplicitamente le entità correlate come in this link. Ma voglio sapere perché EF odia il mio modello di dati.

RISPOSTA: MySQL Connector non è in grado di gestire la seconda entità inclusa nidificata. Getta NotSupportedException, non .NET EF. Questo stesso errore era presente anche quando ho provato questo usando EF4.0, ma la mia ricerca in quel momento mi portò a credere che fossero le entità auto-localizzanti a causare il problema. Ho provato ad aggiornare all'ultimo Connector, ma ha iniziato a causare uno Out of Sync error. Questo è yet another reason per me odiare MySQL.

+0

Cosa succede se * only * lascia il 'Include' lì che hai segnato come" cattivo "e rimuovi gli altri due Include? Funziona allora? – Slauma

+0

@Slauma Sì, la seconda linea funziona da sola. Ho fatto più test e sembra che sia la combinazione di 2a e 3a include che causa l'arresto. Lavorano da soli, ma non insieme. La raccolta FieldValidationTables è caricata da una vista nel database e ho dovuto impostare manualmente la relazione nel modello EF. Ha i campi FieldDefinitionId e TableName. FieldDefintion 1 <-> * FieldValidationTable –

+0

Non ho idea di quale sia questo problema. Probabilmente è necessario aggiungere ulteriori dettagli alla domanda per ottenere una risposta (in pratica per rendere il problema riproducibile per altre persone in un semplice modello di esempio). – Slauma

risposta

2

ho fatto una piccola applicazione console per testare lo scenario e questa applicazione test funziona:

using System; 
using System.Collections.Generic; 
using System.Data.Entity; 
using System.Linq; 

namespace EFIncludeTest 
{ 
    public class Parent 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public ICollection<ChildLevel1> ChildLevel1s { get; set; } 
    } 

    public class ChildLevel1 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public ICollection<ChildLevel2a> ChildLevel2as { get; set; } 
     public ICollection<ChildLevel2b> ChildLevel2bs { get; set; } 
    } 

    public class ChildLevel2a 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
    } 

    public class ChildLevel2b 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
    } 

    public class MyContext : DbContext 
    { 
     public DbSet<Parent> Parents { get; set; } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      // Create entities to test 
      using (var ctx = new MyContext()) 
      { 
       var parent = new Parent 
       { 
        Name = "Parent", 
        ChildLevel1s = new List<ChildLevel1> 
        { 
         new ChildLevel1 
         { 
          Name = "FirstChildLevel1", 
          ChildLevel2as = new List<ChildLevel2a> 
          { 
           new ChildLevel2a { Name = "FirstChildLevel2a" }, 
           new ChildLevel2a { Name = "SecondChildLevel2a" } 
          }, 
          ChildLevel2bs = new List<ChildLevel2b> 
          { 
           new ChildLevel2b { Name = "FirstChildLevel2b" }, 
           new ChildLevel2b { Name = "SecondChildLevel2b" } 
          } 
         }, 

         new ChildLevel1 
         { 
          Name = "SecondChildLevel1", 
          ChildLevel2as = new List<ChildLevel2a> 
          { 
           new ChildLevel2a { Name = "ThirdChildLevel2a" }, 
           new ChildLevel2a { Name = "ForthChildLevel2a" } 
          }, 
          ChildLevel2bs = new List<ChildLevel2b> 
          { 
           new ChildLevel2b { Name = "ThirdChildLevel2b" }, 
           new ChildLevel2b { Name = "ForthChildLevel2b" } 
          } 
         }, 
        } 
       }; 

       ctx.Parents.Add(parent); 
       ctx.SaveChanges(); 
      } 

      // Retrieve in new context 
      using (var ctx = new MyContext()) 
      { 
       var parents = ctx.Parents 
        .Include(p => p.ChildLevel1s.Select(c => c.ChildLevel2as)) 
        .Include(p => p.ChildLevel1s.Select(c => c.ChildLevel2bs)) 
        .Where(p => p.Name == "Parent") 
        .ToList(); 

       // No exception occurs 
       // Check in debugger: all children are loaded 

       Console.ReadLine(); 
      } 
     } 
    } 
} 

La mia comprensione è che questo rappresenta in sostanza il modello e la query che si sta cercando (considerando anche i vostri commenti a la tua domanda in considerazione). Ma da qualche parte deve essere una differenza importante che non è visibile nei frammenti di codice nella tua domanda e che fa fallire il tuo modello.

Modifica

Ho testato l'applicazione console lavorando sopra con il fornitore MS SQL (SQL Server 2008 R2 espresso DB), non MySQL Connector. Apparentemente questa era la "differenza importante".

+0

Una revisione più approfondita dello stack trace fa sembrare che sia il software MySQL Connector a generare un'eccezione. In altre parole, MySQL Connector non fa in modo proattivo che ciò avvenga, non EF4.1. –

+0

@Kasey: Bene, hai trovato la fonte del problema! Non è la prima limitazione di EF MySQL Connector che ho visto qui. – Slauma

+0

Sì, ho incontrato così tante limitazioni e bug con MySQL. Vorrei poter tornare indietro nel tempo e avviare questo progetto con MSSQL. –

3

Forse un po 'in ritardo alla festa, ma ho trovato la seguente soluzione piuttosto utile in un progetto in corso:

IQueryable<FileDefinition> query = db.FileDefinitions 
    .Include(x => x.FieldDefinitions.Select(y => y.DefinitionChangeLogs.Select(z => z.FieldDefinition.FieldValidationTables))) 

Dove invece di usare una seconda fila di include, utilizzare Selezionare per tornare alla navigazione originale proprietà e un altro Selezionare per andare avanti alla proprietà che è necessario includere.

+0

Grazie per il lavoro. Non sono più coinvolto in quel progetto, ma spero che possa aiutare gli altri. Sto anche evitando gli ORM di ritardo. –

Problemi correlati