.net Comparación ORM

Estaba hablando con alguien sobre Entity Framework, y todavía no me gusta mucho, pero me gustaría aprenderlo. Sin embargo, todavía estoy un poco confundido si debo aprenderlo o no. He escuchado a muchas personas decir que no se debe usar el encuadre de la entidad, sin embargo, no he presentado ningún argumento sobre por qué.

Entonces mi pregunta es, ¿cuáles son los pros y los contras de usar el Entity Framework comparado con otros productos ? Me gusta

  • NHibernate
  • DataObjects.Net
  • etc.

En términos de facilidad de uso, capacidad de prueba, semántica …

Sé que hay algunas preguntas duplicadas sobre esto. Pero todos están un poco desactualizados (2008,2009) y para ser honesto, los argumentos también carecen de algo. Sé que Entity Framework 4.0 está disponible, y aún no he encontrado una buena (completa) comparación.


Respuestas

Algunas de las personas agradables aquí han respondido mi pregunta explicando algunos detalles sobre los diferentes marcos. Pensé que sería bueno mostrarlos aquí para futuras referencias.

  • J. Tihon ha hecho una excelente publicación explicando cómo hacer que el EF funcione cuando necesites más extensibilidad.
  • Diego Mijelshon ha creado una respuesta con algunos de los escollos de EF y cómo NHibernate los resuelve.

Dado que J. Tihon hizo un gran trabajo explicando las funciones de EF, enumeraré las áreas en las que NHibernate ejecuta círculos en torno a EF:

  • Almacenamiento en caché
    • EF no tiene nada fuera de lo común; solo hay una muestra no compatible
    • NH tiene soporte completo de caché, incluida la invalidación basada en DB. También es extensible y está basado en el proveedor, lo que significa que funciona con diferentes tipos de cachés locales y distribuidos.
  • Batching
    • EF no tiene ninguno
    • NH tiene un amplio soporte para grupos de entidades o colecciones de carga diferida a la vez (en cualquier DB) y cambios persistentes de la misma manera (Oracle y SQL Server). También hay MultiQueries y Consultas futuras, lo que le permite agrupar arbitrariamente diferentes consultas que se enviarán en una ida y vuelta.
  • Tipos de usuario
    • EF no tiene extensibilidad en absoluto. Ni siquiera es compatible con las propiedades de Enum
    • Ninguna asignación de tipos está codificada en NH. Puede ampliarlo para admitir cualquier tipo de valor que pueda crear, modificar la forma en que se mapean los tipos existentes, etc.
  • Soporte de colección
    • EF solo admite colecciones simples de entidades. Muchos a muchos siempre usa una clave compuesta
    • NH admite colecciones de entidades, tipos de valores, tipos de componentes y también colecciones y diccionarios indexados (donde tanto la clave como el valor pueden ser de cualquier tipo). Colecciones de muchos a muchos con su propia clave son compatibles (idbag)
  • Explotación florestal
    • EF no tiene logging fuera de la caja. Hay la misma muestra no admitida en la lista anterior
    • NH tiene un registro extenso, lo que le permite depurar problemas fácilmente. Utiliza log4net de manera predeterminada, pero puede usar cualquier marco de registro que desee
  • Consultando
    • EF tiene LINQ como el lenguaje de consulta principal. LINQ tiene una alta impedancia cuando se asigna a bases de datos relacionales. El proveedor de EF no admite el uso de entidades como parámetros; siempre tienes que usar Ids. También hay un lenguaje de consulta que está poco documentado
    • NH tiene LINQ (no tan completo como EF’s), HQL, QueryOver y Criteria.
  • Sistema de eventos e interceptores
    • EF no tiene casi nada
    • NH tiene un poderoso sistema de eventos que le permite extender o reemplazar su comportamiento en cualquier momento de la vida de la sesión: cargar objetos, cambios persistentes, enrojecimiento, etc.

Creo que la extensibilidad es el principal punto de venta. Cada aspecto de NH está correctamente desacoplado del rest, utilizando interfaces y clases base que puede ampliar cuando lo necesite y expuesto en las opciones de configuración.

EF sigue el patrón de MS habitual de cerrar las cosas de manera predeterminada, y veremos qué es extensible más adelante.

Paso una gran cantidad de tiempo para doblar el Marco de la Entidad a mis necesidades y, por lo tanto, puedo decir que cumple la mayoría de los requisitos que desea de un ORM. Pero algunos aspectos son demasiado complejos, ya que otros ORM han demostrado que puede ser más fácil.

Por ejemplo, comenzar con Entity Framework es bastante fácil, ya que puede simplemente iniciar el Diseñador en Visual Studio y tener un ORM funcional en cuestión de minutos. Pero terminas con Entity-Classes vinculadas al ObjectContext creado por el diseñador (esto se puede evitar usando una Plantilla T4 personalizada). Esto no es necesariamente algo malo, pero es ese tipo de enfoques de Microsoft “Getting Started”, que no desea utilizar en una aplicación real.

Pero si profundiza en Entity Framework, verá cómo puede evitar la mayoría de sus trampas: Designer genera un archivo EDMX, que (si lo mira en un editor XML) no es más que una combinación de los tres. aspectos principales de un ORM, el almacenamiento físico (su base de datos), el modelo conceptual (sus clases de entidad) y el mapeo entre ambos. La acción de comstackción personalizada aplicada a los archivos .edmx en Visual Studio dividirá esas 3 partes en tres archivos separados y los agregará al ensamblaje como recursos integrados. Al crear un ObjectContext, la ruta a esos tres archivos se usa en ConnectionString (que siempre me parece un poco confuso). Lo que puedes hacer aquí, es hacer todo esto por ti mismo. Esto significa escribir el esquema de almacenamiento, el modelo conceptual y el mapeo en un editor XML (muy parecido a NHibernate) e incrustarlos en el ensamblaje que contiene su modelo.

La base de la clase base de Entity Framework “ObjectContext” puede construirse a partir de esos tres archivos (se necesita un MetadataWorkspace y EntityConnection), pero el punto es que usted tiene control total sobre cómo se creó get ObjectContext. Esto abre la puerta a una gran cantidad de funcionalidades que quizás no esperas de Entity Framework. Por ejemplo: puede incrustar múltiples esquemas de almacenamiento SSDL en el mismo ensamblaje para que coincida con un tipo de base de datos específico (generalmente agrego uno para SQL Server y uno para SQL Server CE 4.0). Y cree una sobrecarga de constructor que elija el esquema de almacenamiento apropiado para un tipo específico de DbConnection.

Como ahora tiene su propia implementación de ObjectContext, puede implementar varias interfaces en ella. Como su propio IRepository, pero como me gusta el enfoque ObjectContext, creo algo como:

interface ICatalog { IEntitySet
{ get; } void Save(); } interface IEntitySet : IQueryable { void Add(T); void Remove(T); } class EntityFrameworkCatalog : ICatalog { ... }

Pero crear un Repositorio si tiene un ObjectContext de Entity Framework es realmente fácil, además de obtener un IQueryable. En base a esta información, puede evitar tener un fuerte acoplamiento de clases entre sus servicios y el ORM y burlarse completamente del marco de la entidad en las pruebas. Además, al probar la implementación de Entity Framework, puede usar una base de datos de SQL Server CE durante las pruebas unitarias para asegurarse de que sus asignaciones sean correctas (por lo general, los diferentes entre el esquema de almacenamiento para CE y el SQL Server completo son solo unos pocos datos). tipos). Por lo tanto, puede probar realmente todos los comportamientos de su implementación de Entity Framework.

Esto hace que Entity Framework se adapte bien a los conceptos de software modernos, pero no impone dichas prácticas en usted, lo que facilita el “Primeros Pasos”.

Ahora a los bits complejos: Entity Framework tiene un pequeño conjunto de tipos de CLR admitidos, que básicamente solo incluyen los primitivos, como ints, strings y byte-arrays. También proporciona algún nivel de tipos complejos, que siguen las mismas reglas. Pero, ¿qué sucede si tiene una propiedad de entidad compleja, como una representación DOM de un documento, que le gustaría serializar en XML en la base de datos? Por lo que sé, NHibernate ofrece una función llamada IUserType, que le permite definir una asignación de este tipo para usted. En Entity Framework, esto se vuelve mucho más complicado, pero todavía es bonito a su manera. El modelo conceptual le permite incluir tipos complejos internos de ensamblaje (siempre y cuando le cuente al ObjectContext al respecto (ObjectContext.CreateProxyTypes (Type [])). Así que puede crear un contenedor para su tipo original, que solo se conoce por el Marco de la Entidad así:

  class Document : IXmlSerializable { } class Article { public virtual Document Content { get; set; } } internal class EntityFrameworkDocument : Document { public string Xml { get { // Use XmlSerializer to generate the XML-string for this instance. } set { // Use XmlSerializer to read the XML-string for this instance. } } } 

Aunque EF ahora puede devolver esos documentos serializados del almacenamiento, escribiéndolos en él, requiere que intercepte el almacenamiento de un Artículo y reemplace un Documento simple con el EntityFrameworkDocument uno, para asegurar que EF pueda serializarlo. Estoy seguro de que otros ORM lo hacen con bastante facilidad y empeoran. Actualmente no hay forma de hacer lo mismo con la clase System.Uri (que es inmutable, pero que de lo contrario funcionaría) o con un Enum. Además de esas restricciones, puede ajustar el EF a la mayoría de sus necesidades. Pero pasarás mucho tiempo en él (como yo).

Como mi experiencia con otros ORM es limitada, resumiría:

  • Entity Framework está en el GAC, incluso en el perfil del cliente
  • Entity Framework se puede personalizar para representar incluso tipos de entidades complejos (Incluyendo algunos muchos a muchos que se auto referencian, por ejemplo, o la serialización XML anterior)
  • Se puede “abstraer”, por lo que puede adherirse a IRepository, etc.
  • Implementación IQueryable (aunque no es tan completa como DataObjects.Net)
  • Solo requiere System.Data y System.Data.Entity, incluso puede incluir varios esquemas de almacenamiento para otros proveedores que normalmente requerirían una referencia, pero si se atiene a DbConnection, puede hacer esto:

    ICatalog Create(DbConnection connection, string storageSchemaPath) ICatalog CreateMySql(DbConnection mySqlConnection) { return Create(connection, "res://Assembly/Path.To.Embedded.MySql.Storage.ssdl"); }

Editar Hace poco descubrí que si las entidades y la implementación de su “catálogo” están en el mismo ensamblaje, puede usar las propiedades internas para un proceso de serialización XML. Por lo tanto, en lugar de derivar un EntityFrameworkDocument interno del Document , puede agregar una propiedad interna denominada Xml a la clase del Document . Esto solo se aplica si tiene control total sobre sus entidades, pero elimina la necesidad de interceptar cualquier cambio en el catálogo, para asegurarse de que se utiliza su clase derivada. El CSDL tiene el mismo aspecto, EF solo permite que la propiedad mapeada sea interna. Todavía tengo que asegurarme de que esto funcione en entornos de confianza media.

Espero que estos completamente ayudarán

  • NHibernate vs Entity Framework

  • ORM abierto vs Entity Framework

  • Muy buena comparación

Cuando usamos ADO.NET desde el principio, tarde o temprano nos frustramos y empezamos a buscar otras soluciones. He probado muchos de ellos. La mayoría de esos marcos ORM tienen muchas características y requieren mucho conocimiento. Algunos parecen muy fáciles al principio (por ejemplo: EF, Castle ActiveRecord) pero hay muchas cosas que te interesarán:

  • Almacenamiento en caché
  • Relaciones muchas-a-muchas
  • Carga lenta
  • Herencia
  • Teclas compuestas
  • Cómo encapsular la infraestructura de las personas que llaman
  • Cómo se generan las sentencias SQL
  • Actuación
  • Cómo hacer consultas avanzadas de bases de datos

Si usted es un desarrollador experimentado y está listo para todas esas trampas y cosas, entonces le pregunto: ¿Son sus compañeros de trabajo también?

Hay formas más fáciles de codificar ADO.NET y no perder el control de lo que está sucediendo. Eche un vistazo a PainlessDAL .

La encoding “elegante” no siempre es la mejor manera.