work with useful unit the pattern hamedani generic framework example c# domain-driven-design repository repository-pattern unit-of-work

c# - with - repository pattern obsolete



Interacción entre unidad de trabajo y patrones de repositorio. (3)

En nuestro proyecto, usamos un Repositorio para comportarnos como una colección de Entidades, y UnitOfWork se usa para rastrear los cambios en esas entidades y para volver a escribirlos en el almacén de datos.

Si está utilizando LinqToSql o algún otro Mapeador de OR, entonces es probable que implemente un patrón UnitOfWork en sí mismo, por lo que a menudo solo utilizamos la instancia de ORMapper en nuestro propio IUnitOfWork.

Nuestra interfaz de repositorio suele ser algo así como ...

IEnumerable<Order> FindByCustomerId(string customerId); void Add(Order order); void Remove(Order order);

No tenemos ningún método de guardar en el Repositorio. Si no necesitamos un UnitOfWork, los métodos de Agregar / Eliminar actúan directamente en el almacén de datos.

Si necesitamos un UnitOfWork, entonces la interfaz pública es algo así como ...

void Commit(); void Rollback();

El repositorio tiene una interfaz interna con UnitOfWork, por lo que cuando consultamos el repositorio, UnitOfWork hace un seguimiento de los objetos devueltos para detectar cambios. El método de confirmación vuelve a escribir los cambios en el almacén de datos, el método de reversión simplemente borra los cambios.

Cuando usamos LinqToSql, el DataContext se encarga del seguimiento de cambios, en Rollback simplemente instanciamos un nuevo Contexto. Se maneja la persistencia, a través de la raíz y sus hijos. Una instancia de UnitOfWork se comparte entre todos los Repositorios.

Cuando no usamos LinqToSql, implementamos nuestro propio UnitOfWork, tal vez se llame un servicio web o algo así, en este caso hacemos un seguimiento de cambios en las clases de entidades usando una clase EntityBase.

Tenemos un repositorio para cada raíz, pero a veces los hijos de una raíz se usan como raíces, por lo que a menudo necesitamos algo como un OrderLineRepository, porque tenemos un caso de uso en nuestro sistema donde el usuario desea buscar líneas de pedido.

Después de leer muchos artículos, todavía no estoy seguro de las responsabilidades del patrón de Unidad de Trabajo al interactuar con los repositorios.

Los repositorios son responsables de cargar y guardar entidades raíz agregadas, así que considere el siguiente código de ejemplo:

using(IUnitOfWork uow = container.CreateUnitOfWork()) { Repository<ARoot> roots = container.GetRepository<ARoot>(); ARoot root = root.FindByName("ARoot"); root.Name = "ANewName"; roots.Save(root); uow.Commit(); }

La interfaz de la unidad de trabajo se definiría con los siguientes métodos:

public interface IUnitOfWork { void Insert(object); void Update(object); void Delete(object); void Commit(); void Rollback(); }

Digamos que el repositorio se implementa utilizando un Asignador de SQL muy sencillo, por lo que FindByName contiene algún SQL directo para devolver ARoot, la implementación de Guardar sería algo como esto:

public void Save(T entity) { IUnitOfWork uow = GetUnitOfWork(); // Tell the UOW we are updating this entity uow.Update(entity); }

¿El código de compromiso de la unidad de trabajo luego construiría todo el SQL requerido para mapear la entidad nuevamente en la base de datos?

Pregunta 2)

Si agrego una raíz agregada a la Unidad de trabajo, ¿es la unidad de trabajo la responsable de la revisión de la raíz y sus actividades secundarias, o debería ser el método Guardar del repositorio agregar las entidades modificadas a la Unidad de Trabajo? p.ej

public void Save(T entity) { IUnitOfWork uow = GetUnitOfWork(); // Tell the UOW we are updating this entity uow.Update(entity); uow.Update(entity.AChildObject); }

O ... alternativamente

Una Unidad de trabajo solo se ocupa de las raíces agregadas, y cuando se compromete llama al repositorio Guarde los métodos para cada objeto en su conjunto de cambios, manteniendo el código de mapeo SQL para que la entidad permanezca en el Repositorio, cambiando el primer ejemplo de código

using(IUnitOfWork uow = container.CreateUnitOfWork()) { Repository<ARoot> roots = container.GetRepository<ARoot>(); ARoot root = root.FindByName("ARoot"); root.Name = "ANewName"; //roots.Save(root); uow.Update(root); // and commit uow.Commit(); }

Gracias,

James


Normalmente, la forma en que me gusta verlo hecho es que UoW rastrea los cambios que se guardan llamando directamente a IRepository.Save ().

También prefiero que el código UoW sea manejado como un aspecto y fuera de las interacciones con el dominio. Esto significa que es manejado por algunos manejadores de comandos globales o el código de servicios web como parte de completar la solicitud. En otras palabras, al comenzar una solicitud se abre una unidad de trabajo y al finalizarla se cierra. De esta manera, el dominio puede ignorar la UoW y su implementación.

Comprometer la unidad de trabajo es lo que hace que los cambios realizados al llamar a .Save () y otros métodos de cambio se conserven. Posiblemente, el UoW es lo que está rastreando estos cambios de alguna manera.


  • UnitOfWork es tu manejador de transacciones
  • El repositorio está haciendo el trabajo real para cargar / guardar objetos en el almacén de datos

Yo uso definiciones similares a:

IUnitOfWork { Commit(); } IRepository { GetAll(); GetById(); Add(T item); Remove(T item); }

No tendría el UnitOfWork creando SQL, esa lógica estaría en su Repositorio. ¿Qué almacén de datos estás usando?