none
Entity Framework: Demasiados nombres de tabla en la consulta. El máximo permitido es 256. RRS feed

  • Pregunta

  • Buenas.

    Tengo la siguiente consulta realizada en Entity Framework:

    IQueryable<TablaPrincipal> query = (from principal in contexto.TablaPrincipal.Include("Tabla1").Include("Tabla2.Tabla3.Tabla4").Include("Tabla5.Tabla6.Tabla7").
    Include("Tabla8.Tabla9").Include("Tabla10.Tabla11").Include("Tabla12.Tabla13.Tabla14").Include("Tabla15").
    Include("Tabla16.Tabla17").Include("Tabla18.Tabla19").Include("Tabla20.Tabla21.Tabla22").Include("Tabla23").
    Include("Tabla24.Tabla25.Tabla26") select principal);


    //Y después lo cargo en un BindingList
    BindingList<TablaPrincipal> result = new BindingList<
    TablaPrincipal>();

     foreach (TablaPrincipal item in query)
     {
            result.Add(item);
     }



    Simplemente es una tabla de la que se cargan todas sus relaciones, ya que necesito todos esos datos a la vez.
    El problema es que el SQL que quenera es larguísimo y sobrepasa el límite permitido en SQL Server.
    Me da la siguiente excepción:


    Se produjo un error al ejecutar la definición del comando. Vea la excepción interna para obtener detalles.

    Inner Exception:
    Demasiados nombres de tabla en la consulta. El máximo permitido es 256.
    Sintaxis incorrecta cerca de ')'.
    Sintaxis incorrecta cerca de ')'.
    Sintaxis incorrecta cerca de ')'.


    ¿Cómo puedo solucionar esto?


    Gracias.

    martes, 2 de diciembre de 2008 8:25

Respuestas

  • Estimado:
    La alternativa es quitar algunos Include del query principal y cargar esas entidades usando la instrucción Load.  Cuáles quitar dependerá de lo que aporte mayor claridad a tu código.
    La sintaxis es:
    Code Snippet

    contexto.TablaPrincipal.TablaX.Load();


    Si la entidad dependiente es una referencia, el Load está en la referencia:
    Code Snippet

    contexto.TablaPrincipal.TablaYReference.Load();


    Otra alternativa sería esperar el EF 2, que probablemente (de acuerdo al clamor generalizado) incorporará una opción de Lazy Load.

    Saludos.
    viernes, 12 de diciembre de 2008 10:55

Todas las respuestas

  • Estimado:
    La alternativa es quitar algunos Include del query principal y cargar esas entidades usando la instrucción Load.  Cuáles quitar dependerá de lo que aporte mayor claridad a tu código.
    La sintaxis es:
    Code Snippet

    contexto.TablaPrincipal.TablaX.Load();


    Si la entidad dependiente es una referencia, el Load está en la referencia:
    Code Snippet

    contexto.TablaPrincipal.TablaYReference.Load();


    Otra alternativa sería esperar el EF 2, que probablemente (de acuerdo al clamor generalizado) incorporará una opción de Lazy Load.

    Saludos.
    viernes, 12 de diciembre de 2008 10:55
  • Muchísimas gracias. Es lo que andaba buscando.

    A ver si sale el 2...
    viernes, 12 de diciembre de 2008 12:27
  • Hola, también piensa que es menos costoso el traerse más información de la necesaria a memoria que el hacer 50 joins contra la base de datos. Podrás comprobar con el profiler de SQL Server que la consulta que lanzas con esa query es bastante salvaje.

     

    Así que creo que deberías de traerte más de lo necesario y después filtrarlo cuando ya lo tienes en memoria.

     

    un saludo Smile

     

    viernes, 12 de diciembre de 2008 17:35
  • Buenas.
    Lo del profiler la yo miré y vi que la consulta SQL era una salvajada, pero el caso es que cargo un montón de tablas completas (de las cuales necesito todos los datos) mediante el método Include.
    ¿Cómo dices entonces de traer toda esa información?

    Muchísimas gracias por vuestro tiempo.

    Un saludo.
    lunes, 15 de diciembre de 2008 8:04
  • La verdad es que lo que no parece normal es que te haga falta traerte toda esa información, puede que debas de revisar tu modelo relacional. A lo que me refería con "traerte toda esa información" es ahorrarte unos cuantos JOIN o SELECT en la consulta trayéndote más información de la necesaria y luego filtrarla cuando ya la tengas recuperada, no sé si me explico.

     

    Creo que sería mejor que un procedimiento almacenado te recuperara toda esa información en vez de generar esa consulta tan salvaje. Aquí te dejo el enlace al soporte de procedimientos almacenados en Entity Framework : http://msdn.microsoft.com/en-us/library/bb399203.aspx

     

    Un saludo Smile

    lunes, 15 de diciembre de 2008 9:44
  • Gracias por el enlace. Lo dejo aquí en español por si alguien lo necesita:

    http://msdn.microsoft.com/es-es/library/bb399203.aspx


    A ver si ya me puedes ayudar con la última preguntita:

    ¿Cómo puedo cargar una tabla completa en el mismo ObjectContext donde antes he cargado otra información?

    Ejemplo:

    Cargo los registtros relacionados de 3 tablas mediante el Include. Ahora quiero cargar otra tabla también relacionada pero esta la quiero cargar con todas las filas porque tengo que hacer muchas operaciones en memoria. Cargarla entera y que mantenga las relaciones con las tres tablas anteriores.
    ¿Cómo se puede hacer esto?

    Muchas gracias y un saludo.
    lunes, 15 de diciembre de 2008 15:21
  • La verdad es que creo que quieres hacer demasiadas cosas en el mismo método, pero bueno, pega algo de código porque la verdad es que no me situo.

     

    Pero piensa mejor en entidades y en recuperar una colección de entidades y no en recuperar "datos". Mejorarás la arquitectura que estás creando.

     

    Un saludo.

    miércoles, 17 de diciembre de 2008 15:10
  • Hola.

    Cuando me refiero a cargar otra tabla entera me refiero a esto.

    Primero cargo los productos con su marca:

    ContextoObjetos.
    Producto.Include("Marca").Execute(MergeOption.PreserveChanges);

    El tema es que la tabla marca necesito cargarla completa.
    Esto se debe a 2 cosas: unsa veces necesito hacer operaciones en memoria y la otra es que a veces tengo ComboBox en el que se selecciona la marca del producto.


    Me está sirviendo de mucha ayuda.
    Muchas Gracias.
    jueves, 18 de diciembre de 2008 18:04
  • La verdad es que sigo sin entenderte, sería de mucha ayuda si adjuntas el diagrama de tu modelo relacional y nos explicas qué grafo quieres recuperar de la base de datos.

     

    Un saludo Smile

     

    viernes, 19 de diciembre de 2008 15:39
  • Perdona Vicente si no me he explicado correctamente.

    Vamos a suponer que la tabla Marca tiene 5 registros.
    El caso es que cuando hago esto:

    ContextoObjetos.Producto.Include("Marca").Execute(MergeOption.PreserveChanges);

    sólo se cargan las filas relacionadas con la tabla producto, que son 2.
    Yo necesito que se cargen los productos y las 5 filas de marca y que las 2 que están relacionadas con producto tengan las relaciones cargadas.

    Aquí están los datos que serían para que te hagas una idea.

    _____________________________
    ProductoID   Nombre        MarcaID
    _____________________________
    1                 Queso            1
    2                 Mayonesa      2
    3                 Tranchetes     1
    4                 Quesitos        1
    _____________________________



    ____________________
    MarcaID   Nombre
    ____________________
    1             El Caserío
    2             Ibarra
    3             Nestle
    4             Carrefour
    5             Pascual
    ____________________



    Es decir que sólo se cargarían las marcas con id 1 y 2, pero q mí me gustaría que estuvieran todas cargadas.

    Si hace falta pongo el modelo relacional.

    Un saludo y gracias.
    lunes, 22 de diciembre de 2008 7:57
  • Hola Luilly, disculpa por haber tardado tanto...

     

    Te voy a poner un ejemplo que he encontrado en la página 358 del libro ADO.NET Entity Framework Aplicaciones y servicios centrados en datos de Unai Zorrilla, Octavio Hernández y Eduardo Quintás.

     

    Verás, es una consulta de LINQ en la que hace un encuentro agrupado entre una tabla de paises y una tabla de personas, la consulta te da la lista de paises con el número de personas que pertenecen a cada país (cero o más). El título del ejemplo es "Encuentros agrupados" y es una manera de simular lo que en el mundo de las bases de datos se conoce como "encuentros externos" u "outer joins".

     

    Creo que no es una consulta trivial, vas a tener que utilizar, preferentemente, Linq.

     

    Creo que, en tu caso, sería algo así:

     

             var resultado = from marca in ContextoObjetos.Marca

     orderby marca.Nombre

     join producto in ContextoObjetos.Producto

           on marca.MarcaID equals producto.MarcaID

    into gp

    select new {

    Marca = marca.Nombre;

    Cantidad = gp.Count();

    };

     

    No obstante, pega el modelo relacional de esas dos tablas y a ver si podemos aproximarnos más a lo que tú quieres, pero ten en cuenta que no va a ser trivial Smile

     

    Imagínate que en vez del Count de cada colección, pues te devuelve una lista de los productos relacionados con cada marca...

     

    Un saludo y Feliz Año Smile

    miércoles, 31 de diciembre de 2008 0:22