2010-09-15 22 views
5

Estoy pensando en iniciar un nuevo proyecto usando EF 4 y pasando por algunos artículos de trabajo, me encontré con un artículo sobre EF con el patrón de repositorio y unidad de trabajo (http://blogs.msdn.com/b/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx)entidad unidad de marco + repositorio + o pregunta

Al mirar ese artículo, usa ObjectContext como UnitOfWork y lo pasa al Repository.

Mi pregunta es: ¿qué ocurre si tengo 2 ObjectContext que significa que tendré 2 unidades de trabajo, pero realmente quiero que toda la operación en esos 2 contextos sea una sola unidad de trabajo? ¿Es posible este escenario? No quiero llamar a ahorrar en cada contexto, me gustaría que sea transaccional .... sin necesidad de utilizar TransactionScope ...

Por ejemplo, tengo un contexto que gestiona el registro de operaciones y otro contexto que gestiona Pedidos. Digamos que en mi capa de negocios, tengo un método llamado AddOrder(). AddOrder() usará el contexto del pedido para crear un nuevo pedido, pero también usará el contexto del registro de operaciones para crear una nueva entrada del registro de operaciones. Ya que esos son 2 contexto, voy a tener que llamar a ahorrar en el contexto tanto de cometer .... tal vez la única opción es tener sólo un único contexto ....

EDIT: Me refería 2 contexto de diferentes tipos por ejemplo: OperationalLogContext y OrderContext.

Respuesta

12

Sí - creo que es posible.

El truco es cómo manejar los repositorios.

Por ejemplo, cada repositorio debe tener un contexto .. por lo que acaba de crear un contexto y pasarlo a cada repositorio.

(código por favor!) Glad u preguntó :)

public interface IOrderRepository 
{ 
    IQueryable<Order> FindAll(); 
} 

public interface IOperationLogRepository 
{ 
    IQueryable<OperationLog> FindAll(); 
} 

public interface IUnitOfWork 
{ 
    void Commit(); 
} 

.

public class SqlServerContext : ObjectContext, IUnitOfWork 
{ 
    public void SqlServerContext(string connectionString) 
     : base(connectionString) 
    { 
    } 

    public void Commit() 
    { 
     this.SaveChanges(); 
    } 

    // Your other POCO's and stuff here ..etc.. 
} 

.

public class OrderRepostiory : IOrderRepository 
{ 
    private readonly SqlServerContext _sqlServerContext; 
    public void OrderRepostiory(SqlServerContext sqlServerContext) 
    { 
     _sqlServerContext = sqlServerContext; 
    } 

    public IQueryable<Order> FindAll() 
    { 
     _sqlServerContext.Orders; 
    } 
} 

.. y, finalmente, de instancias. Hacer que el unicornio un buen chico/chica/arco iris, que estaría utilizando la inyección de dependencias ..

public class SqlServerRegistry : Registry 
{ 
    public SqlServerRegistry(string connectionString) 
    { 
     For<SqlServerContext>() 
      .HybridHttpOrThreadLocalScoped() 
      .Use<SqlServerContext>() 
      .Ctor<string>("connectionString") 
       .Is(connectionString); 

     For<IOrderRepository>().Use<OrderRepository>(); 
     For<IOperationLogRepository>().Use<OperationLogRepository>(); 
    } 
} 

y porque el SqlServerContext se define como HttpOrThreadLocal, será instantied ONCE y reutilizado en múltiples repositorios.

no conocen o entienden DI/COI?

entonces esto también funcionaría ....

private SqlServerContext _sqlServerContext; 
private IOrderRepository _orderRepository; 
private IOperationLogRepository _operationLogRepository; 

[TestInitialize] 
public void TestInitialise() 
{ 
    _sqlServerContext = new SqlServerContext(
      ConfigurationManager.AppSettings["connectionString"]); 
    _orderRepository = new OrderRepository(_sqlServerContext); 
    _operationLogRepository= new OperationLogRepository(_sqlServerContext); 
} 

[TestMethod] 
public void SomeTest() 
{ 
    // Arrange. 
    const int count = 10; 

    // Act. 
    var orders = _orderRepository.FindAll().Take(10).ToArray(); 

    // Assert. 
    Assert.IsNotNull(orders); 
    CollectionAssert.AllItemsAreNotNull(orders); 
    Assert.AreEqual(count, orders.Length); 
} 

una vez más, eso es todo el código no probado, que me acaba de escribir arriba, cuando estaba pensando sobre la respuesta a esta pregunta.

HTH.

+0

Gracias, esto ayuda mucho. Entonces, la única forma es realmente tener solo un contexto ... y si tengo 2 contextos, entonces no tendré más remedio que recurrir a algún mecanismo de transacción, ¿es correcto? – pdiddy

+0

no. Puedes tener tantos como quieras. observe cómo, con la Inyección de Dependencia, dije HttpScopeOrThreadScope? Puede cambiar eso para que sea singleton (mala idea) o el valor predeterminado que es 'nuevo' subir una nueva instancia cada vez que se solicite un objeto.Así que depende de usted :) Si está haciendo la 2da vía (lo cual hice usando un ejemplo de Prueba), entonces sí ... tendrá que actualizar manualmente cada contexto, uno por uno. ej. 'var context1 = new SSC (..); var context 2 = new SSC (...); _or = new OR (context1); _olr = new OLR (context2); 'etc. –

+0

Tuve que actualizar mi respuesta, tenía un error grave. Reemplacé cualquier referencia a una 'nueva EntityConnection (connectionString)' con un plain 'connectionString' porque la conexión no se eliminaba, si el contexto no creaba la' EntityConection' (en lugar de que se pasara uno). Saludos a Ayende Rahien (de Hibernating Rhino) por la solución. –