usando tutorial repositorio proyecto patron net mvc las framework español completo capas asp c# entity-framework ef-code-first repository viewmodel

tutorial - patron repositorio c#



Usando modelos de vista con patrón de repositorio (3)

Bueno, para mí asignaría ViewModel a los objetos del Modelo y los usaría en mis repositorios para fines de lectura / escritura, ya que tal vez sepas que hay varias herramientas que puedes hacer para esto, en mi caso personal utilizo automapper que encontré muy fácil de implementar.

intente mantener la dependencia entre la capa web y las capas de repositorio lo más separadas posible, diciendo que las reposiciones deben hablar solo con el modelo y su capa web debe hablar con sus modelos de vista.

Una opción podría ser que pueda usar los DTO en un servicio y hacer un mapa automático de esos objetos en la capa web (podría ser el caso de ser un mapeo uno a uno), la desventaja es que puede terminar con un montón de código repetitivo y la Dtos y modelos de vista podrían sentirse duplicados.

la otra opción es devolver los objetos parcialmente hidratados en su modelo y exponerlos como DTO y mapear esos objetos a sus modelos de vista; esta solución puede ser un poco oscura pero puede hacer las proyecciones que desea y devolver solo la información que necesita .

puede deshacerse de los modelos de vista y exponer los dtos en su capa web y usarlos como modelos de vista, menos código, pero más acercamiento acoplado.

Estoy usando la arquitectura de aplicación N-layered dominada por Dominio con el EF code first en mi proyecto reciente, definí mis contratos de Repository , en la capa de Domain . Un contrato básico para hacer que otros Repositories menos detallados:

public interface IRepository<TEntity, in TKey> where TEntity : class { TEntity GetById(TKey id); void Create(TEntity entity); void Update(TEntity entity); void Delete(TEntity entity); }

Y Repositories especializados para cada Aggregation root , por ejemplo:

public interface IOrderRepository : IRepository<Order, int> { IEnumerable<Order> FindAllOrders(); IEnumerable<Order> Find(string text); //other methods that return Order aggregation root }

Como puede ver, todos estos métodos dependen de las Domain entities . Pero en algunos casos, la UI de UI una aplicación necesita algunos datos que no son Entity , que pueden obtenerse a partir de dos o más datos de enteritis ( View-Model ). En estos casos, defino los View-Model en la Application layer . porque dependen estrechamente de Application''s necesidades de una Application''s y no del Domain .

Entonces, creo que tengo dos formas de mostrar datos como View-Models en la UI :

  1. El Repository especializado depende solo de las Entities y asigna los resultados del método de los Repositories a View-Models cuando quiero mostrarlos al usuario (en la Application Layer generalmente).
  2. Agregue algunos métodos a mis Repositories especializados que devuelven sus resultados como View-Models directamente, y use estos valores devueltos, en la Application Layer y luego en la UI (estos contratos de los Repositories especializados a los que los llamo Readonly Repository Contract , colocados en la Application Layer diferencia Los otros Repositories e contrato que ponen en Domain ).

Supongamos que mi UI necesita un View-Model con 3 o 4 propiedades (de 3 o 4 grandes Entities ). Es posible que los datos se generen con una proyección simple, pero en el caso 1, debido a que mis métodos no pudieron acceder a View-Models , tengo que buscar todos los campos de las 3 o 4 tablas con algunas combinaciones enormes, y luego asignar los resultados a View-Models . Pero, en el caso 2, simplemente podría usar la proyección y completar los View-Model directamente.

Entonces, creo que en el punto de vista del rendimiento, el caso 2 es mejor que el caso 1. pero leí que el Repository debería depender de las Entities y no View-Models en el punto de vista del diseño.

¿Hay alguna forma mejor de no hacer que la capa de Domain dependa de la Application layer y que tampoco afecte el rendimiento? o ¿es aceptable que para las consultas de lectura, mis Repositories dependan de View-Models ? (caso 2)


Estoy de acuerdo con Pedro aquí. El uso de una capa de servicio de aplicación podría ser benéfico. Si busca un tipo de implementación de MVVM, le aconsejaría crear una clase de modelo que sea responsable de mantener los datos que se recuperan utilizando la capa de servicio. Mapear los datos con automapper es una muy buena idea si sus entidades, DTO y modelos se nombran de manera consistente (para que no tenga que escribir muchas asignaciones manuales).

En mi experiencia, usar tus entidades / poco en los modelos de visualización para mostrar datos resultará en grandes bolas de barro. Las diferentes vistas tienen diferentes necesidades y todas agregarán la necesidad de agregar más propiedades a una entidad. Lentamente haciendo sus consultas más complejas y lentas.

Si sus datos no cambian, a menudo es posible que desee considerar la introducción de vistas (sql / database) que transfieran parte del trabajo pesado a la base de datos (donde está altamente optimizado). EF maneja las vistas de la base de datos bastante bien. Luego, recuperar la entidad y asignar los datos (desde las vistas) al modelo o DTO se vuelve bastante sencillo.


Tal vez el uso de la separación de comando-consulta (en el nivel de la aplicación) podría ayudar un poco.

Debería hacer que sus repositorios dependan solo de las entidades y mantener solo el método de recuperación trivial , es decir, GetOrderById () , en su repositorio (junto con crear / actualizar / fusionar / eliminar, por supuesto). Imagine que las entidades, los repositorios, los servicios de dominio, los comandos de la interfaz de usuario, los servicios de aplicación que manejan esos comandos (por ejemplo, un determinado controlador web que maneja las solicitudes POST en una aplicación web, etc.) representan su modelo de escritura , el lado de escritura de su aplicación.

Luego, construya un modelo de lectura separado que podría ser tan sucio como desee: coloque allí las combinaciones de 5 tablas, el código que lee de un archivo el número de estrellas en el Universo, lo multiplica por el número de libros que comienzan con A (después de haciendo una consulta a Amazon) y construye una estructura n-dimensional que, etc., le da la idea :) Pero, en el modelo de lectura, no agregue ningún código que se ocupe de modificar sus entidades. Usted es libre de devolver cualquier modelo de vista que desee de este modelo de lectura, pero puede activar cualquier cambio de datos desde aquí.

La separación de lecturas y escrituras debería disminuir la complejidad del programa y hacer que todo sea un poco más manejable. Y también puede ver que no romperá las reglas de diseño que mencionó en su pregunta (con suerte).

Desde el punto de vista del rendimiento, usar un modelo de lectura , es decir, escribir el código que lee los datos por separado del código que escribe / cambia los datos es lo mejor que puede obtener :) Esto se debe a que incluso puede destrozar algunos códigos SQL allí. sin dormir mal por la noche, y las consultas de SQL, si están bien escritas, le darán a su aplicación un impulso de velocidad considerable.

Nota bene: Bromeé un poco sobre qué y cómo puede codificar su lado de lectura. El código del lado de lectura debe ser tan limpio y simple como el código del lado de escritura, por supuesto :)

Además, puede deshacerse de la interfaz del repositorio genérico si así lo desea, ya que simplemente desordena el dominio que está modelando y obliga a cada repositorio concreto a exponer métodos que no son necesarios :) Vea this . Por ejemplo, es muy probable que el método Delete () nunca se use para OrderRepository , ya que, tal vez, las órdenes nunca deben borrarse (por supuesto, como siempre, depende). Por supuesto, puede mantener las primitivas de gestión de filas de la base de datos en un solo módulo y reutilizar esas primitivas en sus repositorios concretos, pero no exponer esas primitivas a nadie más que a la implementación de los repositorios, simplemente porque no son necesarios en ningún otro lugar y puede confundir a un programador ebrio si se expone públicamente.

Finalmente, quizás también sería beneficioso no pensar en la Capa de dominio , Capa de aplicación , Capa de datos o Capa de modelos de vista de una manera demasiado estricta. Por favor lea this. Empaquetar sus módulos de software por su significado / propósito ( o característica ) en el mundo real es un poco mejor que empaquetarlos en base a un criterio antinatural , difícil de entender , difícil de explicar a un niño de 5 años , es decir, envasándolos por capa .