NHibernate vs LINQ to SQL

117

Como alguien que no ha usado ninguna de las dos tecnologías en proyectos del mundo real, me pregunto si alguien sabe cómo estos dos se complementan y cuánto se superponen sus funcionalidades.

Manu
fuente

Respuestas:

113

LINQ to SQL le obliga a utilizar el patrón de tabla por clase. Los beneficios de usar este patrón son que es rápido y fácil de implementar y requiere muy poco esfuerzo para que su dominio se ejecute en función de una estructura de base de datos existente. Para aplicaciones simples, esto es perfectamente aceptable (y muchas veces incluso preferible), pero para aplicaciones más complejas, los desarrolladores a menudo sugerirán el uso de un diseño controlado por dominio. patrón de (que es lo que facilita NHibernate).

El problema con el patrón de tabla por clase es que la estructura de su base de datos tiene una influencia directa sobre el diseño de su dominio. Por ejemplo, supongamos que tiene una tabla de Clientes con las siguientes columnas para contener la información de la dirección principal de un cliente:

  • Dirección
  • Ciudad
  • Estado
  • Código Postal

Ahora, digamos que también desea agregar columnas para la dirección postal del cliente, de modo que agregue las siguientes columnas a la tabla Clientes:

  • Correo Calle Dirección
  • MailingCity
  • MailingState
  • MailingZip

Con LINQ to SQL, el objeto Cliente en su dominio ahora tendría propiedades para cada una de estas ocho columnas. Pero si estuviera siguiendo un patrón de diseño controlado por dominio, probablemente habría creado una clase de Dirección y su clase de Cliente tendría dos propiedades de Dirección, una para la dirección postal y otra para su dirección actual.

Ese es un ejemplo simple, pero demuestra cómo el patrón de tabla por clase puede conducir a un dominio algo maloliente. Al final, depende de ti. Nuevamente, para aplicaciones simples que solo necesitan la funcionalidad básica CRUD (crear, leer, actualizar, eliminar), LINQ to SQL es ideal debido a su simplicidad. Pero personalmente me gusta usar NHibernate porque facilita un dominio más limpio.

Editar: @lomaxx: sí, el ejemplo que usé fue simplista y podría haberse optimizado para funcionar bien con LINQ to SQL. Quería mantenerlo lo más básico posible para llevar a casa el punto. Sin embargo, el punto sigue siendo que hay varios escenarios en los que hacer que la estructura de su base de datos determine la estructura de su dominio sería una mala idea, o al menos conduciría a un diseño OO subóptimo.

Kevin Pang
fuente
4
Puede codificar la implementación de su repositorio usando Linq To SQL, es muy útil.
Nicolas Dorier
1
Creo que no es ActiveRecord, incluso las clases mapeadas encapsulan parte de la lógica de la infraestructura. El patrón ActiveRecord sería si pudiera tener Customer.Save (). L2S implementa el patrón Unit of Work con la clase DataContext, como Session en nHibernate, pero NH tiene un enfoque POCO real.
Hrvoje Hudo
1
@kevin "LINQ to SQL usa el patrón de registro activo" Eso no es correcto. Es como decir que ADO.NET usa un registro activo o que NHibernate usa un registro activo. Todas son tecnologías de acceso a datos y no imponen ningún patrón de acceso a datos en particular. Personalmente, me gusta usar linq-to-sql con el patrón de repositorio. Tiene razón en que linq-to-sql no admite asignaciones complejas como lo hace NHibernate.
liammclennan
1
¿Qué hay de normalizar su base de datos y dejar que su DAL sea generado por herramientas, es decir, SQLMetal?
Alex
3
@CoffeeAddict Cuando la falta de coincidencia de impedancia es demasiado para soportar, es cuando su aplicación es demasiado complicada para usar LINQ to SQL, en mi opinión. La razón por la que mi ejemplo huele mal es porque el uso de LINQ to SQL daría como resultado 8 propiedades en lugar de 2 y restringe su capacidad para hacer cosas como implementar funciones que toman una clase de dirección o implementar rutinas en la clase de dirección que podría hacer si hubiera utilizado NHibernate.
Kevin Pang
26

Dos puntos que se han perdido hasta ahora:

Además, la nueva interfaz fluida para Nhibernate parece hacer que sea menos doloroso configurar el mapeo de Nhibernate. (Eliminando uno de los puntos débiles de Nhibernate)


Actualizar

Linq a Nhiberate es mejor en Nhiberate v3 que ahora está en alfa . Parece que Nhiberate v3 podría enviarse a finales de este año.

El Entity Frame Work a partir de .net 4 también está empezando a parecer una opción real.

Ian Ringrose
fuente
2
Linq to NHibernate se encuentra todavía en una etapa muy temprana. No es una implementación completa y, posiblemente, no está lista para su uso en producción.
liammclennan
La nueva versión de LinqConnect 2.0 presenta algunas características adicionales para mayor comodidad, como compatibilidad con la herencia de tabla por tipo, compatibilidad con PLINQ y la funcionalidad de actualizaciones por lotes. ORM Designer (Devart Entity Developer) ahora tiene compatibilidad con Model First y función de sincronización de mapeo. Más detalles: devart.com/news/2010/dotconnects600.html
Devart
23

@Kevin: Creo que el problema con el ejemplo que presenta es que está utilizando un diseño de base de datos deficiente. Pensé que crearías una tabla de clientes y una tabla de direcciones y normalizarías las tablas. Si hace eso, definitivamente puede usar Linq To SQL para el escenario que está sugiriendo. Scott Guthrie tiene una gran serie de publicaciones sobre el uso de Linq To SQL que le sugiero que consulte.

No creo que se pueda decir que Linq y NHibernate se complementan, ya que eso implicaría que se podrían usar juntos, y aunque esto es posible, es mucho mejor elegir uno y seguirlo.

NHibernate le permite mapear las tablas de su base de datos a los objetos de su dominio de una manera muy flexible. También le permite utilizar HBL para consultar la base de datos.

Linq to SQL también le permite mapear sus objetos de dominio a la base de datos, sin embargo, usa la sintaxis de consulta Linq para consultar la base de datos

La principal diferencia aquí es que la sintaxis de consulta de Linq es el compilador verifica la en el momento de la compilación para garantizar que sus consultas sean válidas.

Algunas cosas a tener en cuenta con linq es que solo está disponible en .net 3.xy solo es compatible con VS2008. NHibernate está disponible en 2.0 y 3.x, así como en VS2005.

Algunas cosas a tener en cuenta con NHibernate es que no genera sus objetos de dominio, ni genera los archivos de mapeo. Necesita hacer esto manualmente. Linq puede
hacer esto automáticamente por usted.

lomaxx
fuente
15
¿Qué sucede si está escribiendo código en una estructura de base de datos heredada que no puede cambiar porque admite otras aplicaciones? ¿Desea que su modelo de dominio herede el diseño deficiente de la base de datos o desea crear un modelo de dominio rico que pueda variar independientemente de la estructura de la base de datos?
Larry Foulkrod
7

Fluent NHibernate puede generar sus archivos de mapeo basados ​​en convenciones simples. Sin escritura XML y fuertemente tipado.

Recientemente trabajé en un proyecto, donde necesitábamos cambiar de Linq To SQL a NHibernate por razones de rendimiento. Especialmente la forma de L2S de materializar los objetos parece más lenta que el ídem de NHibernate y la gestión de cambios también es bastante lenta. Y puede resultar difícil desactivar la gestión de cambios para escenarios específicos en los que no es necesaria.

Si va a usar sus entidades desconectadas del DataContext, en escenarios WCF por ejemplo, puede tener muchos problemas para conectarlas al DataContext nuevamente para actualizar los cambios. No he tenido problemas con eso con NHibernate.

Lo que extrañaré de L2S es principalmente la generación de código que mantiene las relaciones actualizadas en ambos extremos de las entidades. Pero supongo que hay algunas herramientas para que NHibernate también lo haga ...

asgerhallas
fuente
2
En caso de que otros lean su publicación y también estén pensando en abandonar el barco, .ObjectTrackingEnabled = falsesu DataContextproblema de seguimiento de cambios habría resuelto. Siempre que acepte el patrón de unidad de trabajo y no busque hacer DDD, Linq-to-SQL realmente cumple.
mattmc3
" Necesitábamos cambiar de Linq To SQL a NHibernate por razones de rendimiento " - Habiendo usado [Fluent, nada menos] NHibernate durante algunos años, lo siento por usted. Creo que en su mayoría hicimos trampa y terminamos escribiendo SQL nativo para puntos de presión de rendimiento reales. Sería interesante escuchar una actualización (seis años después ...) sobre cómo fue su migración y si valió la pena.
ruffin
5

¿Puede aclarar lo que quiere decir con "LINQ"?

LINQ no es una tecnología de acceso a datos, es solo una función de lenguaje que admite consultas como una construcción nativa. Puede consultar cualquier modelo de objeto que admita interfaces específicas (por ejemplo, IQueryable).

Mucha gente se refiere a LINQ To SQL como LINQ, pero eso no es del todo correcto. Microsoft acaba de lanzar LINQ To Entities con .NET 3.5 SP1. Además, NHibernate tiene una interfaz LINQ, por lo que puede usar LINQ y NHibernate para obtener sus datos.

Jon Galloway
fuente
2

Por LINQ, supongo que te refieres a LINQ to SQL porque LINQ, por sí mismo, no tiene ninguna base de datos asociada. Es solo un lenguaje de consulta que tiene una gran cantidad de azúcar sintáctico para que parezca SQL.

En el más básico de los ejemplos básicos, NHibernate y LINQ to SQL parecen estar resolviendo el mismo problema. Una vez que lo aprueba, pronto se da cuenta de que NHibernate tiene soporte para muchas características que le permiten crear modelos de dominio verdaderamente ricos. También hay un proyecto LINQ to NHibernate que le permite usar LINQ para consultar NHibernate de la misma manera que usaría LINQ to SQL.

Ryan Rinaldi
fuente
1

Primero, separemos dos cosas diferentes: el modelado de bases de datos se preocupa por los datos mientras que el modelado de objetos se preocupa por las entidades y relaciones.

La ventaja de Linq-to-SQL es generar rápidamente clases a partir del esquema de la base de datos para que puedan usarse como objetos de registro activo (consulte la definición del patrón de diseño de registro activo).

La ventaja de NHibernate es permitir flexibilidad entre el modelado de objetos y el modelado de bases de datos. La base de datos se puede modelar para reflejar mejor sus datos teniendo en cuenta el rendimiento, por ejemplo. Si bien su modelado de objetos reflejará mejor los elementos de la regla de negocio utilizando un enfoque como el Diseño controlado por dominio. (ver comentario de Kevin Pang)

Con bases de datos heredadas con modelado deficiente y / o convenciones de nomenclatura, Linq-to-SQL reflejará estas estructuras y nombres no deseados en sus clases. Sin embargo, NHibernate puede ocultar este lío con los mapeadores de datos.

En proyectos totalmente nuevos donde las bases de datos tienen un buen nombre y poca complejidad, Linq-to-SQL puede ser una buena opción.

Sin embargo, puede usar Fluent NHibernate con mapeos automáticos para este mismo propósito con mapeo como convención. En este caso, no se preocupe por ningún mapeador de datos con XML o C # y deje que NHibernate genere el esquema de la base de datos a partir de sus entidades en función de una convención que puede personalizar.

Por otro lado, la curva de aprendizaje de Linq-to-SQL es más pequeña que NHibernate.

Humberto
fuente
0

O puede utilizar el proyecto Castle ActiveRecords. Lo he estado usando por un corto tiempo para aumentar un código nuevo para un proyecto heredado. Utiliza NHibernate y trabaja en el patrón de registro activo (sorprendente dado su nombre, lo sé). No lo he intentado, pero supongo que una vez que lo haya usado, si siente la necesidad de pasar directamente al soporte de NHibernate, no sería demasiado hacerlo para parte o para todo su proyecto.


fuente
0

Como escribió "para una persona que no ha usado ninguno de ellos", LINQ to SQL es fácil de usar, por lo que cualquiera puede usarlo fácilmente. También admite procedimientos, lo que ayuda la mayor parte del tiempo. Suponga que desea obtener datos de más de una tabla, luego escriba un procedimiento y arrastre ese procedimiento al diseñador y creará todo por usted, suponga que el nombre de su procedimiento es "CUSTOMER_ORDER_LINEITEM" que obtiene el registro de estas tres tablas y luego simplemente escriba

MyDataContext db = new MyDataContext();
List<CUSTOMER_ORDER_LINEITEMResult> records = db.CUSTOMER_ORDER_LINEITEM(pram1, param2 ...).ToList<CUSTOMER_ORDER_LINEITEMResult>();

también puede usar su objeto de registros en foreach loop, que no es compatible con NHibernate

Ali Adravi
fuente