2009-02-06 23 views
18

Estoy comenzando un nuevo proyecto y he decidido tratar de incorporar los patrones DDD y también incluir Linq en Entidades. Cuando miro el ObjectContext de EF parece estar desempeñando las funciones de los patrones Repositorio y Unidad de trabajo:Entity Framework como Repository y UnitOfWork?

Repositorio en el sentido de que la interfaz de nivel de datos subyacente se abstrae de la representación de entidad y puedo solicitar y guardar datos a través del ObjectContext.

Unidad de trabajo en el sentido de que puedo escribir todas mis inserciones/actualizaciones en el objectContext y ejecutarlas todas de una vez cuando hago un SaveChanges().

Parece redundante colocar otra capa de estos patrones encima del EF ObjectContext? También parece que las clases de modelo se pueden incorporar directamente en la parte superior de las entidades generadas por EF usando 'clase parcial'.

Soy nuevo en DDD, por favor avíseme si me falta algo aquí.

Respuesta

17

No creo que el marco de la entidad es una buena aplicación de depósito, debido a que:

  • El contexto del objeto no es lo suficientemente abstracto para hacer el bien prueba de la unidad de las cosas, que hacen referencia a él, ya que está obligado a el acceso DB. En cambio, tener una referencia de IRepository funciona mucho mejor para crear pruebas unitarias.
  • Cuando un cliente tiene acceso a ObjectContext, el cliente puede hacer casi cualquier cosa que le interese. El único control real que tiene sobre esto es hacer que ciertos tipos o propiedades sean privados. Es difícil implementar una buena seguridad de datos de esta manera.
  • En un modelo no trivial, ObjectContext no es suficientemente abstracto. Puede, por ejemplo, tener asignadas tablas y procedimientos almacenados al mismo tipo de entidad. Realmente no desea que el cliente tenga que distinguir entre las dos asignaciones.
  • En una nota relacionada, es difícil escribir reglas comerciales completas y aplicar correctamente el código de entidad. De hecho, si esto es incluso una buena idea es discutible.

Por otro lado, una vez que tenga un ObjectContext, implementar el patrón Repositorio es trivial. De hecho, para los casos que no son particularmente complejos, el Repositorio es una especie de envoltorio alrededor de los tipos ObjectContext y Entity.

+2

Gracias Craig. Encontré un código en un blog de Simon Segal en http://www.simonsegal.net/blog/2009/01/13/entity-framework-repository-specifications-and-fetching-strategies/ que proporciona ejemplos de implementación de repositorio para Entity Framework. – Weej

+0

¿Actualmente usa EntityFramework en sus diseños? ¿Hay alguna dificultad en la implementación? Gracias de nuevo – Weej

+0

Sí, estamos usando Entity Framework. No hay ninguna dificultad en la implementación de Repository alrededor; es trivial Tenemos todo tipo de dificultades con el Marco de la Entidad en sí mismo; Creo que esto es probablemente cierto para cualquier ORM. –

7

Yo diría que debería ver el ObjectContext como su UnitOfWork, y no como un repositorio.

Un ObjectContext no puede ser un repositorio -imho- ya que es 'genérico'. Debe crear sus propios repositorios, que tienen métodos especializados (como GetCustomersWithGoldStatus, por ejemplo) junto a los métodos regulares de CRUD.

Entonces, lo que haría sería crear repositorios (uno para cada raíz de agregado) y dejar que esos repositorios usen el ObjectContext.

+0

Gracias por los comentarios Frederik. ¿Implementarías GetCustomersWithGoldStatus directamente en el repositorio? ¿Has considerado usar métodos de extensión? ¿Crees que los métodos de extensión tienen un lugar en este escenario? – Weej

+0

¿En qué tipo crearías tal método de extensión? De hecho, lo crearía en el repositorio, pero no como un método de extensión. El repositorio se puede considerar como 'la colección' de donde obtienes entidades, por lo que creo que es un lugar válido para hacerlo de esta manera –

0

Me gustaría tener una capa de repositorio para las siguientes razones:

EF de Gotcha

Cuando nos fijamos en algunos de los tutoriales actuales sobre EF (Código de Primera versión), es evidente que hay una número de gotcha a ser manejado, particularmente alrededor de gráficos de objetos (entidades que contienen entidades) y escenarios desconectados. Creo que una capa de repositorio es ideal para envolverlos en un solo lugar.

una imagen clara de los mecanismos de acceso a datos

Un repositorio da una imagen específica en cuanto a cómo el BL está accediendo y actualizar el almacén de datos. Expone métodos que tienen un único propósito claro y pueden probarse independientemente del BL. Ejemplo estándar de los libros de texto, Find() para encontrar una sola entidad. Un ejemplo más específico de la aplicación, Clear() para borrar una tabla db.

Un lugar para optimizaciones

Inevitablemente subido contra golpes de rendimiento al utilizar EF vainilla. Uso el repositorio para ocultar los mecanismos de optimización del BL.

ejemplos,

GetKeys() para proyectar claves almacenadas en caché de las tablas (para las decisiones INSERT/UPDATE). La lectura de la clave solo es más rápida y utiliza menos memoria que la lectura de la entidad completa.

Carga masiva a través de SqlBulkCopy. EF lo insertará mediante declaraciones SQL individuales. Si desea que una sola instrucción inserte varias filas, SqlBulkCopy es un buen mecanismo. El repositorio encapsula esto y proporciona metadatos para SqlBulkCopy. Además del método Insert, necesita un método StartBatch() y EndBatch(), que también es un argumento para una capa UnitOfWork.