2010-09-15 12 views
5

Sto pensando di iniziare un nuovo progetto utilizzando EF 4 e passando attraverso alcuni articoli il lavoro, ho trovato un articolo su EF con il modello repository e unità di lavoro (http://blogs.msdn.com/b/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx)entità unità quadro + repository + o domanda

Guardando quell'articolo, usa ObjectContext come UnitOfWork e lo passa al Repository.

La mia domanda è cosa succede se ho 2 ObjectContext, il che significa che avrò 2 unità di lavoro, ma in realtà voglio che tutte le operazioni eseguite in quei 2 contesti siano un'unica unità di lavoro, è possibile questo scenario? Non voglio chiamare save su ogni contesto, mi piacerebbe che fosse transazionale .... senza usare transactioncope ...

Ad esempio, ho un contesto che gestisce il log delle operazioni e un altro contesto che gestisce Ordini. Diciamo che nel mio livello aziendale, ho un metodo chiamato AddOrder(). AddOrder() utilizzerà il contesto dell'ordine per creare un nuovo ordine, ma utilizzerà anche il contesto del registro delle operazioni per creare una nuova voce del registro delle operazioni. Dal momento che quelli sono in 2 contesto, dovrò chiamare save su entrambi i contesti per commettere .... forse l'unica opzione è avere un solo contesto ....

EDIT: Intendevo 2 contesti di tipi diversi ad esempio: OperationalLogContext e OrderContext.

risposta

12

Sì, credo sia possibile.

Il kicker è come gestire i tuoi repository.

Ad esempio, ciascun repository deve prendere un contesto .. quindi è sufficiente creare un contesto e passarlo a ciascun repository.

(codice per favore!) Sono contento u chiesto :)

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; 
    } 
} 

.. e, infine, di istanze. Causa il vostro un bravo ragazzo/ragazza/arcobaleno unicorno, si sarebbe utilizzando Dependency Injection ..

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>(); 
    } 
} 

e perché lo SqlServerContext è definito come HttpOrThreadLocal, esso sarà instantied ONCE e riutilizzato in più repository.

Non so o non capisco DI/IoC?

allora questo sarebbe anche lavorare ....

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 volta di più, questo è tutto il codice non testato che ho appena scritto su, come stavo pensando a rispondere a questa domanda.

HTH.

+0

Grazie, questo aiuta molto. Quindi l'unico modo è avere un solo contesto ... e se ho 2 contesti, non avrò altra scelta che ricorrere a qualche meccanismo di transazione, è corretto? – pdiddy

+0

no. puoi avere quante ne vuoi. nota come, con la dipendenza da iniezione, ho detto HttpScopeOrThreadScope? Puoi cambiarlo per essere singleton (cattiva idea) o il default che è 'new' su una nuova istanza ogni volta che viene richiesto un oggetto.Quindi spetta a te :) Se stai facendo il 2o modo (che ho fatto usando un esempio di Test), allora sì ... dovresti manualmente rinnovare ogni contesto, uno per uno. ad esempio 'var context1 = new SSC (..); var context 2 = new SSC (...); _or = new OR (context1); _olr = nuovo OLR (context2); 'ecc. –

+0

Ho dovuto aggiornare la mia risposta - Ho avuto un bug grave in esso. Ho sostituito ogni riferimento a una 'nuova EntityConnection (connectionString)' con una semplice 'connectionString' perché la connessione non veniva eliminata, se il contesto non creava' EntityConection' (invece di averne una passata). Saluti a Ayende Rahien (da Hibernating Rhino's) per la correzione. –

Problemi correlati