10

, en este ejemplo here, Scott muestra haciendo una consulta Linq contra el dbContext y vinculando el resultado directamente a un GridView para mostrar una lista de productos. Su ejemplo es usar la versión CTP4 de Code First.Enlace de datos de formularios Web con error de consulta de Código EF Primero-Linq

Sin embargo, cuando intento hacer lo mismo utilizando la última versión de ADO.NET Entity Framework 4.1, me sale el siguiente error:

Data binding directly to a store query (DbSet, DbQuery, DbSqlQuery) is not supported. Instead populate a DbSet with data, for example by calling Load on the DbSet, and then bind to local data.

veo que el objeto DBQuery está lanzando este error a propósito en su implementación de IListSource.GetList(), que se utiliza en enlace de datos.

¿Alguna idea de por qué funciona su ejemplo? Por cierto, sé que puedo hacer que esto funcione poniendo un projects.ToList(). Mi pregunta principal es si algo cambió en la versión de lanzamiento que hace que este tipo de cosas ya no funcione, o si me falta algo en alguna parte que puede evitar este error.

Sólo como referencia, me refiero al código como este:

MyDbContext db = new MyDbContext(); 

var projects = from p in db.Projects 
       where p.AnotherField == 2 
       select p; 

grdTest.DataSource = projects; 
grdTest.DataBind(); 
+0

No sé si algo ha cambiado, pero usted debe llamar 'ToList' de todos modos porque el contexto es desechable y desea deshacerse de él una vez que no lo necesita. Muchas veces esto sucede antes de que la página sea renderizada (y la consulta ejecutada => excepción). 'ToList' se asegurará de que su consulta se ejecute cuando existe el contexto. –

+0

Si bien lo que usted dijo es un buen consejo general, esta pregunta específica es sobre el error anterior y cómo los ejemplos de Scott estaban funcionando. El error que tengo no está relacionado con un contexto faltante b/c que se está lanzando cuando se llama a la llamada a IListSource.GetList() en el objeto DBQuery durante el enlace de datos. – patmortech

+0

Sí, no es la respuesta a su pregunta. Es por eso que lo publiqué como un comentario. –

Respuesta

14

Es una larga historia, pero intentaré que no sea aburrida.

Desde la primera versión de EF admitimos el enlace directamente a las consultas. Obtuvimos suficiente experiencia sobre las trampas y la confusión que esto generó que decidimos desactivarlo explícitamente la nueva API que creamos para EF 4.1. El principal problema para mí fue que WinForms y la infraestructura de enlace de datos de WPF asumen que las fuentes de datos están en la memoria y son de bajo costo para acceder. Esto ha resultado en el enlace de datos a menudo pidiendo la lista de enlaces más de una vez. En EF, el enlace a una consulta reutilizable implicó necesariamente querer los últimos resultados de la base de datos, por lo tanto, lo hicimos de modo que cada vez que se solicita la lista de enlaces, volvemos a ejecutar la consulta en la base de datos. Esto causó al menos dos ejecuciones de consultas cada vez que alguien se vinculó a una consulta.

Hubo algunos otros aspectos vinculantes para consultas que eran bastante confusas o contradictorias para muchos clientes. Exploro cómo funcionaban las cosas en esta publicación de blog: http://blogs.msdn.com/b/diego/archive/2008/10/09/quick-tips-for-entity-framework-databinding.aspx

Lo que se supone que debes hacer con DbContext API es enlazar directamente a los datos locales y no a las consultas. Para eso exponemos DbSet.Local que es una ObservableCollection que funciona bastante bien para WPF y el método ToBindingList que envuelve la colección en BindingList para facilitar el consumo en WinForms.

Veo que el mensaje de excepción podría ser más explícito sobre la existencia de la propiedad local. Consideraré presentar un error para eso.

Esperanza esto ayuda

+0

Gracias! ¿Cómo afecta esto a los escenarios web, si simplemente llamamos a .ToList() o .Local también, supongo? – ssmith

+2

Solo un FYI, el mensaje de excepción completo es explícito sobre la propiedad Local: "No se admite el enlace de datos directamente a una consulta de la tienda (DbSet, DbQuery, DbSqlQuery, DbRawSqlQuery). En su lugar, rellene un DbSet con datos, por ejemplo, llamando a Load on el DbSet, y luego se une a los datos locales. Para WPF se une a DbSet.Local. Para WinForms se une a DbSet.Local.ToBindingList(). " –

+0

Gracias por la explicación. Muy bien con WPF. ¿Pero qué hay de la gente que trabaja con winform? La excepción sugiere una solución para WPF incluso trabajando con winforms. Tuve que hacerlo de la manera difícil cuando agregué y borré nuevas filas. Ver esta publicación: [enlace] (http://stackoverflow.com/questions/11799661/datagridview-allowusertoaddrow-property-doesnt-work/11802151#comment19532695_11802151) –

3

Al analizar el EF4 Característica CTP4 liberación DLL en el reflector, puedo ver que su objeto no implementa DBQuery IListSource.GetList() y lanzar una excepción como lo hace EF 4.1 dll. Supongo que en algún momento tuvieron una razón para no permitir el enlace directamente a la consulta, a pesar de que implementa IEnumerable.

Esto no responde POR QUÉ hicieron este cambio, pero al menos puedo ver que hay una razón por la que funcionaría en la versión anterior.

9

Encontré el mismo problema y encontré este tema. ToList() funcionó:

using (NorthwindContext context = new NorthwindContext()) 
{ 
    var products = from p in context.Products 
        where p.Discontinued == false 
        select p; 

    gridView.DataSource = products.ToList(); 
    gridView.DataBind(); 
} 
+2

Como verá en la pregunta, dije "Sé que puedo hacer que esto funcione al poner un products.ToList()". – patmortech

Cuestiones relacionadas