2011-02-10 18 views
5

Estoy tratando de construir un sistema que siga el repositorio y los patrones de unidad de trabajo para permitir la ignorancia de persistencia/pruebas unitarias, etc. etc. Estoy buscando asesoramiento sobre el manejo de Rollback. Idealmente, quiero usar POCO, pero creo que podría necesitar al menos implementar una interfaz para proporcionar algunas partes.Unidad de trabajo, opciones de reversión

Digamos que tenemos dos repositorios, un contexto/unidad de trabajo.

Agrego un artículo, enmiendo otro artículo y elimino un tercer artículo. Repita para el segundo repositorio, luego invoco la reversión.

En el pasado he usado algo parecido a un DataSet para esto. Cada objeto tiene un estado de pendiente. Nuevo, pendiente. Enmendado, pendiente. Eliminado, limpio. También hay una copia de la última versión persistente del objeto para deshacer.

¿Cómo implementarías esto?

EDIT:

Ok, esto es lo que creo que realmente estoy tratando de sacarlo de mi cabeza. Prepárese para ser modelado :)

En última instancia, el proyecto es WPF MVVM. Así que estamos viendo el Modelo para lo que sea que la tienda esté aquí.

Creo que he estado tratando de combinar el modelo con la idea de repositorio, donde creo que el modelo debe usar el UOW y los repositorios para proporcionar las características que el modelo necesita proporcionar. ¿Eso suena mejor?

Quiero ignorancia de persistencia completa, así que imagine que mi dominio incluye un cliente, un pedido y líneas de pedido.

La GUI, digamos, tiene un botón de orden nuevo que permite al usuario completar los detalles del cliente, detalles del pedido y detalles de 1-n OrderLine. Acierta guardar y van a la base de datos, acierta cancela que no.

Por lo tanto, en este caso, el modelo podría solicitar al CustomerRepository un cliente, luego el OrderRepository para un nuevo pedido, luego el OrderLineRepository para cada nueva línea y luego indicar a la Unidad de trabajo que los guarde.

¿Eso suena razonable? A mí me parece, creo que es donde se define la separación. Estoy medio tentado de tener otra API entre el modelo y los repositorios. No, eso es tonto.

EDIT 2: Este es un excelente artículo que tiene un tipo de helped un poco.

Respuesta

6

Diseñé mi unidad de trabajo y las clases de repositorio similares a cómo se describe here on MSDN. La idea básica de la clase IUnitOfWork es que maneja todo el trabajo de la base de datos.

que añade entonces (a mi clase IUnitOfWork e implementaciones) un método BeginTransaction(), lo que abre un objeto TransactionScope(), y luego añade un método EndTransaction(bool commit). Este método maneja el cierre de la transacción, ya sea al comprometer la transacción con la base de datos (si es verdadera) o al revertir la transacción (si es falsa).

Esto me permite controlar transacciones complicadas que permiten retrotraer múltiples commits.

Editar: Mi línea de pensamiento es que desea que el objeto UnitOfWork para saber acerca de los repositorios y no al revés. Esta es mi opinión, y encontrarás gente a la que le gusta lo opuesto, pero he aquí por qué.

Cuando quiera tratar con la base de datos de alguna manera, querrá que todo esté restringido por su unidad de trabajo actual. Entonces para mí tiene sentido lógico ir a través de la unidad de trabajo para acceder a sus repositorios, en lugar de tener sus repositorios accediendo a su unidad de trabajo.

También lo hace más fácil si necesita ramificar y hacer varias cosas en diferentes bases de datos (por ejemplo, si los datos del historial se escriben en una base de datos diferente a los datos en vivo, o si se está haciendo particiones de bases de datos horizontales), cada base de datos tendría su propia unidad de trabajo. La razón es que si hace que los repositorios conozcan la unidad de trabajo, debe crear una unidad de trabajo para cada base de datos, además de una copia de cada repositorio que necesite para cada unidad de trabajo a la que necesite acceder.

Finalmente, el acceso a sus repositorios como acceso solo a través de su unidad de trabajo mantiene la API simple para los desarrolladores. Para empezar, solo necesita crear una instancia de 1 objeto (la unidad de trabajo) en lugar de 1 unidad de objeto de trabajo más todos los objetos de repositorio que pueda necesitar. Mantiene su código simple (imho) y hace que las cosas sean menos propensas a errores para los desarrolladores.

+0

Ese es un buen artículo, no había visto eso antes. Creo que todavía estoy luchando un poco con qué clases saben qué otras clases, es decir, si el repositorio sabe acerca de la unidad de trabajo. ¿Conoce la unidad de trabajo todos los repositorios? En realidad, esta es una buena pregunta: lo pondré en una edición anterior si está bien ... – Ian

+0

Agregué mi respuesta en una edición, ya que era demasiado tiempo para un comentario – KallDrexx

+0

Kall, eso es casi exactamente cómo lo habría hecho en el pasado, y tiene perfecto sentido para mí :) Lo tomaré como la respuesta, pero si alguien está en desacuerdo vehementemente, por favor diga :) – Ian

2

Es difícil decirlo con seguridad sin más detalles, pero me gustaría implementarlo desde la interfaz IDbConnection y las interfaces asociadas. Te proporciona una interfaz con la que la mayoría de los codificadores de C# estarán familiarizados con cualquier experiencia.

Debajo del capó, para ser honesto, realmente depende de la eficiencia de su mecanismo de almacenamiento. Si maneja muchos cambios de manera eficiente, entonces probablemente sea mejor que su mecanismo de reversión cree una lista de acciones que debería llevar a realizar una reversión, que se descarta en un 'commit'. Si, por otro lado, las actualizaciones son caras, haga que su mecanismo de transacción mantenga una lista de acciones para realizar en un compromiso, que se descartan en una reversión. También debe pensar si otro código debería o no ver actualizaciones antes de una confirmación; con el primer enfoque lo harán, con el segundo, no lo harán.

+0

Sí, estoy obteniendo mucho "depende", y lo valoro completamente. Puedo ver una media docena de formas de hacer implementaciones concretas, y lo he hecho en el pasado, pero está definiendo la abstracción con la que estoy luchando, específicamente hacerlo bajo la luz orientadora de estos patrones. – Ian

0

Implementaré esto usando un marco como NHibernate o Entity Framework para hacer esto.:) NHibernate le permite usar POCO, y ya hace todas las cañerías para usted.

+0

Uno de mis objetivos es tener una capa de persistencia tanto para NHibernate como para EF más allá de la unidad de trabajo. Hay dos proyectos, uno es trabajo real en el mundo real, el otro es equipo de prueba de prototipos y es el equipo en el que estoy trabajando en este momento para obtener la forma del código. – Ian

Cuestiones relacionadas