Entity Framework con sistemas grandes: ¿cómo dividir los modelos?

49

Estoy trabajando con una base de datos de SQL Server con más de 1000 tablas, otros cientos de vistas y varios miles de procedimientos almacenados. Estamos buscando comenzar a usar Entity Framework para nuestros proyectos más nuevos, y estamos trabajando en nuestra estrategia para hacerlo. Lo que me preocupa es cómo dividir mejor las tablas en diferentes modelos (EDMX o DbContext si primero vamos a codificar). Puedo pensar en algunas estrategias de inmediato:

  • Dividir por esquema
    Tenemos nuestras tablas divididas en una docena de esquemas. Podríamos hacer un modelo por esquema. Sin embargo, esto no es perfecto porque dbo sigue siendo muy grande, con más de 500 tablas / vistas. Otro problema es que ciertas unidades de trabajo terminarán teniendo que realizar transacciones que abarcan varios modelos, lo que aumenta la complejidad, aunque supongo que EF lo hace bastante sencillo.
  • Dividir por intención
    En lugar de preocuparse por los esquemas, divida los modelos por intención. Así que tendremos diferentes modelos para cada aplicación, proyecto, módulo o pantalla, dependiendo de cuán granulares deseamos obtener. El problema que veo con esto es que hay ciertas tablas que inevitablemente deben usarse en todos los casos, como Usuario o AuditHistory. ¿Agregamos esos a cada modelo (creo que viola DRY), o están en un modelo separado que es usado por cada proyecto?
  • No dividir en absoluto: un modelo gigante
    Obviamente, esto es simple desde una perspectiva de desarrollo, pero según mi investigación y mi intuición, parece que podría funcionar de manera terrible, tanto en tiempo de diseño, tiempo de compilación y posiblemente en tiempo de ejecución.

¿Cuál es la mejor práctica para usar EF contra una base de datos tan grande? Específicamente, ¿qué estrategias utilizan las personas para diseñar modelos contra este volumen de objetos DB? ¿Hay opciones en las que no estoy pensando que funcione mejor que lo que tengo arriba?

Además, ¿es esto un problema en otros ORM como NHibernate? Si es así, ¿han encontrado mejores soluciones que EF?

    
pregunta RationalGeek 07.09.2012 - 22:18

4 respuestas

30

Personalmente, he intentado hacer un esquema enorme para todas mis entidades en un proyecto bastante complejo pero pequeño (~ 300 tablas). Teníamos una base de datos extremadamente normalizada (5ta. Normalización de la forma (lo digo de forma general)) con muchas relaciones de "muchos a muchos" y una aplicación extrema de la integridad referencial.

También usamos una estrategia de "instancia única por solicitud" que tampoco estoy convencido de haber ayudado.

Cuando se realizan listas simples, razonablemente planas, "explícitamente definidas", las búsquedas y guardan el rendimiento fue generalmente aceptable. Pero cuando comenzamos a profundizar en las relaciones profundas, el rendimiento parecía tomar drásticos descensos. En comparación con un proceso almacenado en este caso, no hubo comparación (por supuesto). Estoy seguro de que podríamos haber modificado el código base aquí y allá para mejorar el rendimiento; sin embargo, en este caso solo necesitábamos un aumento del rendimiento sin análisis debido a limitaciones de tiempo, y recurrimos al proceso almacenado (aún lo mapeamos a través de EF, porque EF proporcionó resultados muy tipográficos), solo necesitábamos eso como un retroceso en algunas áreas. Cuando tuvimos que recorrer toda la base de datos para crear una colección (usando .include () de forma no fragmentada), el rendimiento fue notablemente degradante, pero quizás pedimos demasiado ...

Entonces, en base a mi experiencia, recomendaría crear un .edmx por intento. Solo genere lo que utilizará según el alcance de esa necesidad. Es posible que tenga algunos archivos .edmx de ámbito más pequeño para tareas con propósito y, a continuación, algunos más grandes en los que necesita atravesar relaciones complejas para construir objetos. No estoy seguro de dónde está ese lugar mágico, pero estoy seguro de que hay uno ... jajaja ...

Sin embargo, honestamente, aparte de algunos escollos que vimos venir (complejos recorridos), el enorme .edmx funcionó bien desde una perspectiva "funcional". Pero tendrás que estar atento a la magia de "reparación" que el contexto hace detrás de la escena si no la deshabilitas explícitamente. Además de mantener el .edmx sincronizado cuando se realizan cambios en la base de datos ... a veces era más fácil borrar toda la superficie y volver a crear las entidades, lo que demoró aproximadamente 3 minutos, por lo que no fue un gran problema.

Esto fue todo con EntityFramework 4.1. También me interesaría saber sobre su elección final y su experiencia.

Y respecto a tu pregunta sobre nHibernate, esa es una pregunta de lata de gusanos en mi opinión, tendrás ladridos en ambos lados de la valla ... Escucho a mucha gente atacando a EF por el simple hecho de atacar sin Trabajando a través de los desafíos y entendiendo los matices exclusivos de EF. Y aunque nunca he usado nHibernate en producción, en general, si tiene que crear manualmente y explícitamente cosas como mapeos, tendrá un control más limitado, sin embargo. , si puede arrastrar y soltar, generar e iniciar CRUD'ing y realizar consultas utilizando LINQ, podría dar una mierda sobre la granularidad.

Espero que esto ayude.

    
respondido por el hanzolo 07.09.2012 - 22:41
12

Permítame comenzar con una simple aclaración: no tengo experiencia con una base de datos tan grande, por lo que el resto de mi respuesta no se basa en el ejemplo del mundo real.

Así que tienes una base de datos GRANDE y quieres usarla con ORM / EF. Yo iría con la segunda opción. Aquí está mi explicación simple por qué:

  • La asignación agrega complejidad. No es necesario agregar complejidad con las entidades que su aplicación / proyecto / módulo actual nunca necesita, pero no hace que la granularidad sea un nivel demasiado bajo. Tener un conjunto de mapeo separado por pantalla no te ayudará también.
  • Quieres lograr la unidad de trabajo. Debería poder especificar qué módulo de tablas necesita en la mayoría de los casos (no es necesario en todos los casos). Si coloca estas tablas en un solo conjunto de mapeo, podrá manejar la lectura y la modificación de los datos por instancia de contexto único: ese es su objetivo final.
  • No estoy seguro de lo que quiere decir exactamente por modelo, pero incluso con diferentes conjuntos de mapeo, puede compartir clases entre conjuntos de mapeo usando los mismos tipos de entidad. Entonces, si usa la tabla de Usuario en dos módulos, no necesita dos clases de Usuario para representar lo mismo. Aún puede usar una sola tabla y en el caso de mapeo de código (también conocido como código primero) incluso puede definir el mapeo una vez y cargarlo en múltiples conjuntos de mapeo para que no se viole el principio DRY pero el enfoque de código primero tiene más limitaciones cuando se trata A vistas y procedimientos almacenados. EDMX hace esto más difícil. Aún puede reutilizar las clases pero es imposible reutilizar la asignación.
  • ¿Qué pasa con las consultas de módulos cruzados? Estas consultas pueden ocurrir, pero para ser honesto, no todo debe ser manejado por EF. Puede aprovechar EF para casos comunes para simplificar el acceso regular a los datos, pero si necesita alguna consulta especial que combine tablas pertenecientes a 5 módulos diferentes, simplemente puede ejecutarla directamente o envolverla en un procedimiento almacenado. El reemplazo del 100% del acceso a datos nativos puede ser difícil, complejo y contraproducente.
  • El último punto es simplemente práctico: no creo que las herramientas VS estén listas para trabajar con un conjunto tan amplio de objetos, ni en el diseñador, ni siquiera con la herramienta de importación. Solía trabajar en una base de datos muy grande con acceso a datos tradicionales y un proyecto de Base de datos SQL en VS2008: la experiencia del usuario con un proyecto complejo fue muy mala. Debe mantener bajo el número de tablas usadas: el límite para el diseñador debe estar entre 100 y 200, pero incluso 100 tablas manejadas por contexto único (conjunto de mapeo) suena demasiado responsabilidad para una clase (suponga que tendrá 100 propiedades establecidas) expuesto en el contexto, no parece un buen diseño).
respondido por el Ladislav Mrnka 07.09.2012 - 23:40
3

Yo diría que no puede decidir este tipo de pregunta desde una perspectiva técnica. Le recomendaría que construya su arquitectura en función de sus casos de uso (historias de usuario, etc.). Primero encuentra los objetos de tu negocio. Un objeto de entidad no es por defecto un objeto de negocio. Típicamente tendrá un objeto de negocio frente a los objetos de entidad. Luego puede decidir de manera incremental lo que realmente necesita, según los requisitos del usuario.

"Un buen arquitecto maximiza el número de decisiones que no se toman". Robert C. Martin

enlace

    
respondido por el ollins 10.09.2012 - 20:40
2

Utilizo un enfoque híbrido: las cosas OLTP son manejadas por EF mientras que las operaciones pesadas tales como inserciones por lotes, actualizaciones masivas, consultas de informes, etc. También hace que la ruta de migración sea más fácil si no está haciendo una reescritura completa de su capa de datos de una vez.

    
respondido por el Nik 11.09.2012 - 21:23

Lea otras preguntas en las etiquetas