work unit pattern net mvc example asp .net asp.net-mvc linq-to-sql repository-pattern

.net - net - c# repository pattern unit of work example



LINQ to SQL y el patrĂ³n de repositorio (3)

¿Los objetos generados son serializables? Tenía la impresión de que no lo eran. Es solo un caso de aislamiento como dijo Marc Gravel arriba.

¿Qué pasa si cambia el repositorio y tiene un MySQL, Oracle, archivos XML, servicio web o cualquier proveedor de datos (Repositorio)? Estarías atado al ensamblado LINQ to SQL para hacer referencia a las entidades, ¿verdad? Lo cual, por supuesto, no querrías.

Siento que estoy corriendo en círculos. Parece que no puedo decidir cuál es el patrón de repositorio correcto utilizando LINQ to SQL . Si está familiarizado con MVC Storefront de Rob Conery, verá que su implementación envuelve los modelos generados por LINQ con otra clase y trata el generado por LINQ simplemente como un objeto de transferencia de datos (DTO). Se ve algo como esto:

//Custom wrapper class. namespace Data { public class Customer { public int Id {get;set;} public string Name {get;set;} public IList<Address> Addresses {get;set;} } } //Linq-Generated Class - severly abbreviated namespace SqlRepository { public class Customer { public int Id {get;set;} public string Name {get;set;} public EntitySet<Address> {get;set;} } } //Customer Repository namespace SqlRepository { public class UserRepository : IUserRepository { private _db = new DB(); //This is the Linq-To-Sql datacontext public IQueryable GetCusomters() { return from c in _db.Customers select new Customer // This is the wrapper class not the gen''d one { Id = c.Id, Name = c.Name, Addresses = new LazyList(c.Addresses) }; }

¿Cuál es la ventaja de hacerlo de esta manera (utilizando una clase contenedora), a diferencia de lo que sugiere Mike Hadlow en el uso del patrón IRepository con LINQ to SQL en su versión de IRepository <T> donde simplemente devuelve los objetos DTO del ¿repositorio?

¿Dónde debe aplicarse y verificarse la lógica comercial? ¿Está esto en una capa separada llamada por el repositorio en guardar / actualizar, o está incorporado en la clase contenedora?


Depende de dónde estén definidos los DTO y cómo quiera probarlos. Si usa DBML, entonces LINQ to SQL desea generar los objetos de datos en la capa de datos. Si bien LINQ to SQL es compatible con ignorancia de persistencia, no se desvive por facilitarlo. Entity Framework no lo admite en absoluto.

Esto significa que en el modelo estándar, su capa de datos está definiendo todas las entidades de dominio, lo que es complicado si desea probar las capas de interfaz de usuario / negocio en un verdadero aislamiento de la capa de datos.

Un enfoque pragmático podría ser utilizar las definiciones de objeto de datos de la capa de datos en pruebas unitarias, pero no el contexto de datos (es decir, ocultar el contexto de datos detrás de la interfaz del repositorio, pero exponer los tipos de entidades), pero esto está enturbiando las aguas un poco, y significa que su UI, etc. necesita hacer una fuerte referencia a la capa de datos. Pero si piensa en esto como una "capa de modelo de dominio que también contiene una implementación de repositorio que podemos o no estar usando", puede justificarlo.

Mantener entidades de dominio completamente separadas hace que las pruebas unitarias y la inversión de control (IoC) sean más "puras", pero aumenta la cantidad de código que tiene (de doble filo).


El caso es que LINQ to SQL no es un verdadero Object Relation Mapper (ORM), es un generador de capas de acceso a datos. Puede hacer que sea un ORM profundizando en la edición manual de archivos XML y jugando con SqlMetal y otras cosas, pero donde brilla es como DAL .

La idea detrás de un ORM es esto. Usted tiene su base de datos SQL y sus objetos de dominio. Para diseñar una base de datos correctamente, hará cosas (como la normalización) que lógicamente no se traducen en un modelo de objetos diseñado correctamente, y viceversa. Esto se llama "Impedancia no coincidente", el rol de un ORM es lidiar con ese desajuste de una manera limpia, efectiva y eficiente. La interacción de la base de datos menos dolorosa es casi una cosa secundaria.

La idea detrás de un repositorio es que encapsula toda la lógica de persistencia y las dependencias de la infraestructura del resto de su aplicación. Cuando su aplicación necesita un objeto Cliente, no debería tener que saber si proviene de SQL Server, MySQL, un archivo XML o una Membresía ASP.NET. Una vez que tenga ese desacoplamiento, cualquier cambio que realice en su historia de persistencia no tendrá efecto en el resto de su aplicación.

Con eso en mente, se vuelve más claro por qué hizo lo que hizo. LINQ to SQL se usa para generar el DAL, pero lo único que se debe saber sobre el DAL es el repositorio, por lo que se realiza una traducción a sus objetos de dominio. De esa forma, puede refactorizar su modelo de dominio sin preocuparse por su historia de persistencia, y puede refactorizar su base de datos sin preocuparse por los efectos de ondulación a través de su aplicación. También podría comenzar a codificar en la lógica de negocios antes de decidir cuestiones como qué ORM usar o incluso dónde almacenar sus datos.

Si usara un ORM real (como NHibernate ), ese código de mapeo se maneja en otro lado (ya sea en XML o clases de arranque). Creo que LINQ to SQL (y Robs open source DAL, SubSonic ) son grandes proyectos, pero más diseñados para aplicaciones más pequeñas de dos niveles donde algo así como el patrón de repositorio es excesivo. La tienda también es una buena ilustración de por qué la complejidad adicional de NHibernate puede ser importante. Pudo haberse ahorrado una gran cantidad de código yendo con algo creado para manejar ese tipo de escenario, en lugar de hacerlo todo de forma manual.