inner framework different linq-to-sql linq-to-entities

linq-to-sql - framework - linq to entities join



LINQ a entidades y carga lenta (6)

Entonces, ¿este es un buen diseño de marco? ¿O Microsoft está pensando más en esto para nosotros?

Bueno, analicemos eso: todas las ideas que Microsoft tiene para no tener que convertirnos realmente en programadores más perezosos. Pero, en general, nos hace más productivos (en su mayor parte). Entonces , ¿ están pensando demasiado o solo están pensando para nosotros?

En una polémica publicación de blog de hoy, Hackification pontifica lo que parece ser un error en el nuevo marco de LINQ To Entities:

Supongamos que busco un cliente:

var alice = data.Customers.First( c => c.Name == "Alice" );

Bien, eso funciona bien. Ahora veamos si puedo encontrar uno de sus pedidos:

var order = ( from o in alice.Orders where o.Item == "Item_Name" select o ).FirstOrDefault();

LINQ-to-SQL encontrará la fila secundaria. LINQ-to-Entities silenciosamente no devolverá nada.

Ahora supongamos que repito todas las órdenes en la base de datos:

foreach( var order in data.Orders ) { Console.WriteLine( "Order: " + order.Item ); }

Y ahora repite mi búsqueda:

var order = ( from o in alice.Orders where o.Item == "Item_Name" select o ).FirstOrDefault();

¡Guauu! LINQ-to-Entities me está diciendo repentinamente que el objeto hijo existe, ¡a pesar de haberme dicho antes que no!

Mi reacción inicial fue que esto tenía que ser un error, pero después de una mayor consideración (y respaldada por el equipo de ADO.NET ), me di cuenta de que este comportamiento fue causado por Entity Framework no vago cargando la subconsulta Pedidos cuando se saca a Alice de el contexto de datos.

Esto se debe a que el orden es una consulta LINQ-A-Objeto:

var order = ( from o in alice.Orders where o.Item == "Item_Name" select o ).FirstOrDefault();

Y no está accediendo al contexto de datos de ninguna manera, mientras que su ciclo foreach:

foreach( var order in data.Orders )

Está accediendo al contexto de datos.

LINQ-To-SQL realmente creó propiedades cargadas perezosas para Pedidos, de modo que cuando se acceda, realizaría otra consulta, LINQ to Entities lo deja en manos de usted para recuperar datos relacionados manualmente.

Ahora, no soy un gran admirador de ORM, y esta es precisamente la razón. Descubrí que para tener todos los datos que desea listos al alcance de su mano, ejecutan consultas a sus espaldas repetidamente, por ejemplo, que la consulta de linq-a-sql anterior podría ejecutar una consulta adicional por fila de clientes para obtener pedidos. .

Sin embargo, el EF que no hace esto parece violar mayormente el principio de menor sorpresa. Si bien es una forma técnicamente correcta de hacer las cosas (debe ejecutar una segunda consulta para recuperar pedidos o recuperar todo de una vista), no se comporta como se esperaría de un ORM.

Entonces, ¿este es un buen diseño de marco? ¿O Microsoft está pensando más en esto para nosotros?


No sé mucho sobre ORMs, pero como usuario de LinqToSql y LinqToEntities, espero que cuando intente consultar Orders for Alice haga la consulta adicional cuando haga la consulta linq (en lugar de no consultar nada o consultar todo por cada fila).

Parece natural esperar

from o in alice.Orders where o.Item == "Item_Name" select o

para trabajar dado que esa es una de las razones por las que las personas usan los ORM en primer lugar (para simplificar el acceso a los datos).

Cuanto más leo sobre LinqToEntities, más creo que LinqToSql satisface las necesidades de la mayoría de los desarrolladores. Normalmente solo necesito un mapeo uno a uno de tablas.


Si LINQ-to-Sql y LINQ-to-Entities provienen de dos compañías diferentes, sería una diferencia aceptable: no hay ninguna ley que establezca que todos los LINQ-To-Whatevers deben implementarse de la misma manera.

Sin embargo, ambos provienen de Microsoft, y no deberíamos necesitar un conocimiento profundo de sus equipos y procesos de desarrollo interno para saber cómo usar dos cosas diferentes que, en apariencia, se ven exactamente iguales .

Los ORM tienen su lugar, y de hecho llenan un espacio para las personas que intentan hacer cosas, pero los usos de ORM deben saber exactamente cómo su ORM hace las cosas, tratándolo como una caja negra impenetrable solo lo llevará a problemas.


Aunque no debería tener que conocer los procesos y equipos de desarrollo interno de Microsoft, la realidad es que estas dos tecnologías son dos bestias completamente diferentes.

La decisión de diseño para LINQ to SQL fue, por simplicidad, cargar implícitamente colecciones. El equipo de ADO.NET Entity Framework no quería ejecutar consultas sin que el usuario lo supiera, por lo que diseñaron la API para que se cargue explícitamente para la primera versión.

LINQ to SQL ha sido entregado al equipo de ADO.NET y es posible que vea una consolidación de API en el futuro, o LINQ to SQL se pliegue en Entity Framework, o puede ver la atrofia de LINQ to SQL por negligencia y finalmente quedar obsoleto .


Jon,

He estado jugando con linq a entidades también. Tiene un largo camino por recorrer antes de alcanzar Linux con SQL. Tuve que usar linq para entidades para la tabla por tipo de herencia de texto. Recientemente encontré un buen artículo que explica la totalidad de 1 empresa 2 diferentes tecnologías ORM aquí .

Sin embargo, puede hacer una carga lenta, de alguna manera, al hacer esto:

// Lazy Load Orders var alice2 = data.Customers.First(c => c.Name == "Alice"); // Should Load the Orders if (!alice2.Orders.IsLoaded) alice2.Orders.Load();

o simplemente podría incluir los pedidos en la consulta original:

// Include Orders in original query var alice = data.Customers.Include("Orders").First(c => c.Name == "Alice"); // Should already be loaded if (!alice.Orders.IsLoaded) alice.Orders.Load();

Espero eso ayude.

Dave


Después de haber perdido unos días en este problema, simpatizo.

La "falla", si la hay, es que hay una tendencia razonable a esperar que una capa de abstracción vaya a aislar de este tipo de problemas. Pasar de LINQ, a Entidades, a la capa de base de datos, doblemente.

Tener que cambiar de MS-SQL (usando LingToSQL) a MySQL (usando LinqToEntities), por ejemplo, uno pensaría que el LINQ, al menos, sería el mismo si no solo para ahorrar del costo de tener que volver a escribir el programa lógica.

Tener que ensuciar el código con .Load () y / o LINQ con .Include () simplemente porque el mecanismo de persistencia bajo el capó cambió parece algo molesto, especialmente con una falla silenciosa. La capa LINQ debe al menos comportarse de manera consistente.

Varios marcos ORM usan un objeto proxy para cargar dinámicamente el objeto perezoso de forma transparente, en lugar de simplemente devolver un valor nulo, aunque me hubiera complacido con una excepción de colección no cargada.

Tiendo a no comprar en la excusa de que lo hicieron-deliberadamente-para-su-beneficio; otros marcos ORM le permiten anotar si desea la carga ansiosa o lenta, según sea necesario. Lo mismo podría hacerse aquí.