2010-09-15 5 views
5

Je pense à commencer un nouveau projet en utilisant EF 4 et en passant par des articles, j'ai trouvé un article sur EF avec motif de dépôt et l'unité de travail (http://blogs.msdn.com/b/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx)entité + référentiel unité + ou travail question

En regardant cet article, il utilise ObjectContext comme UnitOfWork et le transmet au Repository. Ma question est que si j'ai 2 ObjectContext ce qui signifie que j'aurai 2 unités de travail, mais je veux que toutes les opérations effectuées sur ces 2 contextes soient une seule unité de travail, ce scénario est-il possible? Je ne veux pas appeler enregistrer sur chaque contexte, je voudrais qu'il soit transactionnel .... sans utiliser transactionscope ...

Par exemple, j'ai un contexte qui gère le journal d'opération et un autre contexte qui gère Ordres. Disons que dans ma couche métier, j'ai une méthode appelée AddOrder(). AddOrder() utilisera le contexte de la commande pour créer une nouvelle commande, mais utilisera également le contexte du journal des opérations pour créer une nouvelle entrée dans le journal des opérations. Puisque ce sont 2 contexte, je vais devoir appeler enregistrer sur les deux contexte à commettre .... peut-être la seule option est d'avoir un seul contexte unique ....

EDIT: Je voulais dire 2 contextes de types différents par exemple: OperationalLogContext et OrderContext.

Répondre

12

Oui - je crois que c'est possible.

Le kicker est la façon dont gérer vos référentiels. Par exemple, chaque référentiel doit prendre un contexte. Il suffit donc de créer un contexte et de le transmettre à chaque référentiel.

(code s'il vous plaît!) Heureux u demandé :)

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

.. et enfin, l'instanciation. Parce que ton un bon garçon/fille/licorne arc en ciel, vous utilisez l'injection de dépendance ..

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

et parce que le SqlServerContext est défini comme HttpOrThreadLocal, il sera instantied UNE FOIS et réutilisé dans plusieurs Référentiels.

Vous ne connaissez pas ou ne comprenez pas DI/IoC?

alors ce serait aussi travailler ....

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

une fois de plus, c'est tout code non testé que je viens tapé, comme je pensais à répondre à cette question.

HTH.

+0

Merci, cela aide beaucoup. Donc la seule façon est de n'avoir qu'un seul contexte ... et si j'ai 2 contextes, alors je n'aurai pas d'autre choix que de recourir à un mécanisme de transaction, est-ce correct? – pdiddy

+0

non. Vous pouvez en avoir autant que vous voulez. remarquez comment, avec l'injection de dépendance, j'ai dit HttpScopeOrThreadScope? Vous pouvez changer cela pour être singleton (mauvaise idée) ou la valeur par défaut qui est de "nouveau" une nouvelle instance chaque fois qu'un objet est demandé.Donc, c'est à vous de choisir :) Si vous faites la 2ème façon (ce que j'ai fait en utilisant un exemple de test), alors ouais .. vous devrez manuellement chaque nouveau contexte, un par un. par exemple 'var context1 = new SSC (..); var context 2 = nouveau SSC (...); _or = new OR (context1); _olr = new OLR (context2); 'etc .. –

+0

Je devais mettre à jour ma réponse - j'avais un bug sérieux dedans. J'ai remplacé toute référence à 'new EntityConnection (connectionString)' par un simple 'connectionString' car la connexion n'était pas éliminée, si le contexte ne créait pas' EntityConection' (au lieu d'en passer un). Bravo à Ayende Rahien (d'Hibernating Rhino) pour le correctif. –

Questions connexes