6

Editar: Se ha actualizado la descripción del problema sobre la base de las pruebas - 12 de septiembre de 2011.EF4.1 entidad anidada múltiple Incluye gets NotSupportedException?

tengo esta consulta que lanza una NotSupportedException siempre que llame .ToList() ("No se admite el método especificado.").

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

Si comento alguna de las líneas que he comentado como "malas", entonces la consulta funciona. También intenté incluir diferentes entidades anidadas en mi modelo de objetos con el mismo efecto. Incluir 2 provocará un bloqueo. Por anidado, me refiero a una propiedad de navegación de una propiedad de navegación. También intenté usar los métodos .Include con una ruta de cadena: el mismo resultado.

Mi estructura de la tabla es el siguiente:

Db model

Db model 2

esto es usar MySQL 5.1 (tablas InnoDB obviamente) como el almacén de base de datos con MySQL Connector/NET 6.3.4.

Así que mi pregunta es: ¿Por qué esto no funciona?

Nota: Puedo hacer que funcione si carga explícitamente las entidades relacionadas como en this link. Pero quiero saber por qué EF odia mi modelo de datos.

RESPUESTA: MySQL Connector aparentemente no es capaz de manejar la segunda entidad anidada incluida. Lanza la NotSupportedException, no .NET EF. Este mismo error también estaba presente cuando probé esto usando EF4.0, pero mi investigación en ese momento me llevó a creer que se trataba de entidades de auto-seguimiento que causaban el problema. Traté de actualizar a la última Connector, pero comenzó a causar un Out of Sync error. Esto es yet another reason para que odie a MySQL.

+0

¿Qué sucede si * solo * deja el 'Incluir 'allí que ha marcado como" malo "y elimina los otros dos? Incluye? ¿Funciona entonces? – Slauma

+0

@Slauma Sí, la 2da línea funciona sola. Hice más pruebas, y parece ser la combinación de 2da y 3ra incluye lo que causa el colapso. Trabajan solos, pero no juntos. La colección FieldValidationTables se carga desde una vista en la base de datos, y tuve que configurar manualmente la relación en el modelo EF. Tiene los campos FieldDefinitionId y TableName. FieldDefintion 1 <-> * FieldValidationTable –

+0

No tengo idea de qué es este problema. Probablemente necesite agregar más detalles a su pregunta para obtener una respuesta (básicamente, para que el problema sea reproducible para otras personas en un modelo de ejemplo simple). – Slauma

Respuesta

2

he hecho una pequeña aplicación de consola para probar su escenario y esta aplicación de prueba funciona:

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

Mi opinión fue que esto representa básicamente el modelo y la consulta que se está tratando (teniendo también sus comentarios su pregunta en cuenta). Pero en algún lugar debe haber una diferencia importante que no sea visible en los fragmentos de código en su pregunta y que haga que su modelo no funcione.

Editar

He probado la aplicación de consola de trabajo anterior con el proveedor de MS SQL (SQL Server 2008 R2 expreso DB), no MySQL Connector. Aparentemente esta era la "diferencia importante".

+0

Una revisión más exhaustiva del seguimiento de la pila hace que parezca que es el software MySQL Connector el que lanza la excepción. En otras palabras, MySQL Connector está pro-activamente no permitiendo que esto ocurra, no EF4.1. –

+0

@Kasey: ¡Qué bueno que hayas encontrado el origen del problema! No es la primera limitación de EF MySQL Connector que he visto aquí. – Slauma

+0

Sí, me he encontrado con tantas limitaciones y errores con MySQL. Ojalá pudiera retroceder en el tiempo y comenzar este proyecto con MSSQL. –

3

Tal vez un poco tarde a la fiesta, pero me encontré con la siguiente solución bastante útil en un proyecto actual:

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

Cuando en lugar de utilizar una segunda fila de incluye, utilice Seleccionar para volver a la navegación originales propiedad y otro Seleccione ir hacia adelante a la propiedad que necesita incluir.

+0

Gracias por la solución. Ya no estoy involucrado en ese proyecto, pero espero que ayude a otros. También estoy evitando los ORM últimamente. –

Cuestiones relacionadas