5

Sono stato in grado di implementare una piccola unità di lavoro per lavorare con il framework di entità.Implementazione UnitOfWork

mi si avvicinò con ..

public class UnitOfWork : IUnitOfWork 
    { 
     private Database _database; 
     private IDatabaseFactory _databaseFactory; 

     private DbTransaction transaction; 

     public UnitOfWork(IDatabaseFactory databaseFactory) 
     { 
      _databaseFactory = databaseFactory; 
      _database = Database; 

      transaction = _database.Database.Connection.BeginTransaction(); 
     } 

     public Database Database 
     { 
      get { return _database ?? (_database = _databaseFactory.Get()); } 
     } 

     public void Dispose() 
     { 
      try 
      { 
       _database.SaveChanges(); 
       transaction.Commit(); 
      } 
      catch (Exception ex) 
      { 
       transaction.Rollback(); 
      } 
     } 
    } 

Sono abbastanza sicuro che ognuno è geloso di questa unità di lavoro ora. (Scherzando)

Ma ho un piccolo problema di progettazione in questo livello di servizio.

public class JournalService : IJournalService 
    { 
     IJournalRepository _journalRepository; 

     public JournalService(IJournalRepository journalRepository) 
     { 
      _journalRepository = journalRepository; 
     } 

     public void AjouterJournal(Journal j) 
     { 
      [B]using (IUnitOfWork uow = new UnitOfWork())[/B] 
      { 
       var journal = new Journal(); 
       journalRepository.AddJournal(journal); 

      } 
     } 
    } 

Il problema è che l'unità di lavoro necessita di un'iniezione di database quindi non posso crearne un'istanza. Non posso fornire un'unità di lavoro direttamente nel livello di servizio perché non avrebbe senso poiché l'unità di lavoro deve essere eliminabile.

E poiché utilizzo il repository per aggiungere la mia roba non è necessario accedere direttamente all'unità di lavoro, il salvataggio avverrà automaticamente quando verrà comunque eliminato.

Potrei iniettare IDatabaseFactory nel mio livello di servizio ma l'idea è di non usarlo lì. In realtà il livello di servizio non dovrebbe saperlo.

Che ne dici di una fabbrica UnitOfWork?

Qualche idea o suggerimento su come posso risolvere questo problema?

Grazie.

+0

Una factory 'UnitOfWork' sembra funzionare. Ma il problema riguarda il modo in cui fornisci 'IDatabaseFactory' al tuo' UnitOfWorkFactory'. – yuxhuang

+0

Iniezione DI nel costruttore? – Rushino

risposta

7

È necessario immettere UnitOfWork in servizio se si desidera utilizzare l'architettura corrente. Il tuo servizio non avrà una dipendenza interna (nascosta) dall'implementazione di UnitOfWork e sarà meglio verificabile. Va di pari passo con molti principi dell'architettura orientata agli oggetti.

Un'altra cosa è che questa implementazione è utilizzabile solo per semplici operazioni CRUD. In servizi più complessi si finirà con la composizione di più operazioni (possibilmente da servizi multipe) che funzioneranno ciascuna con UnitOfWork. Chiamare più SaveChanges (e transazioni) in un'unica operazione commerciale probabilmente non è ciò che si vuole normalmente: in tal caso, si desidera chiamare SaveChanges solo una volta da un servizio di primo livello o dal chiamante del servizio. Lo scenario tipico è che la singola operazione commerciale ha una unità di lavoro con una transazione, ma è possibile eseguire molte operazioni del servizio come parte di questa operazione aziendale.

Un'altra implicazione è la costruzione dei tuoi archivi. Probabilmente hanno bisogno di accedere al Database, vero? Quindi probabilmente stai già iniettando UoW nel costruttore del repository. Se lo fai, puoi evitare la relazione tra UoW e i servizi di base.

+0

Puoi spiegare un po 'di più la seconda parte (sull'implementazione è utilizzabile solo per CRUD semplice ...) Attualmente sto facendo l'iniezione di UoW e repository nel mio livello di servizio. c'è qualcosa di sbagliato in questo? normalmente l'UoW inizia quando viene avviata l'operazione di business e termina dopo la conclusione dell'operazione commerciale nel servizio. Potrei finire per chiamare altri servizi, ma questi servizi avranno solo una relazione con la mia attività commerciale e tali servizi non possono essere accessibili direttamente tramite il controller. Il controller utilizzerà solo un servizio che è probabilmente il servizio nell'effettiva contex – Rushino

+0

L'idea dietro la seconda parte è la composizione. Se la tua attività commerciale è AddJournal, sei pronto a completare UoW e SaveChanges nell'operazione di servizio.Ma se la tua attività commerciale è DoSomethingBig che consiste in diverse chiamate AddJournal, non vorrai chiamare SaveChanges e Commit in ogni chiamata AddJournal. Dovrai chiamarlo solo una volta dopo tutte le chiamate AddJournal. –

+0

Un bravo ragazzo di punto non sapevo che in realtà da callig aggiungi journal usi l'unità di lavoro che non è una buona idea, ma perché chiameresti addjournal dal servizio se invece puoi chiamare repository.addjournal? Credo che la classe di servizio faccia più delle operazioni sporche. Correggimi se sbaglio non è il lavoro grossolano fatto principalmente dal deposito? se dovessi mai aggiungere un diario, non userò il metodo di servizio. Altrimenti Dove suggerisci di mettere l'unità di lavoro in fase di attuazione? Quale livello ? – Rushino