2015-07-08 13 views
14

Attualmente sto provando a utilizzare Dapper ORM con Unit Of Work + Repository Pattern.Come implementare il pattern Unità di lavoro con Dapper?

Desidero utilizzare Unità di lavoro anziché un semplice repository dapper, poiché il mio inserimento e gli aggiornamenti richiedono un certo grado di elaborazione delle transazioni. Non sono stato in grado di trovare alcun esempio utile poiché la maggior parte sembra utilizzare Entity Framework e presentare problemi di dispersione all'interno dell'unità di lavoro.

Qualcuno potrebbe indicarmi la giusta direzione?

+1

Dapper non è un ORM. L'UoW è la transazione db. Il repository utilizzerà dapper per lavorare con il db. – MikeSW

+2

Dapper è un micro ORM, sottolineo che l'UOW è la transazione, ma sto cercando un buon esempio di Dapper che utilizza il modello UOW. – Stig

+1

Il micro ORM è un termine improprio, è fondamentalmente un mappatore di dati. Un buon esempio di dapper usando uow pattern è qualsiasi transazione db. E non usare schemi che non capisci ancora, complicheresti solo la tua vita. Comprendi cosa è il repository, capisci cos'è Uow (leggi le definizioni attuali) e poi usale ** se ** hai quei problemi specifici. Molti sviluppatori stanno usando la combinazione UoW/repository in un modo molto sbagliato. Non essere come loro – MikeSW

risposta

9

Questo Git project è molto utile. Ho iniziato dallo stesso e ho apportato alcune modifiche secondo le mie necessità.

public sealed class DalSession : IDisposable 
{ 
    public DalSession() 
    { 
     _connection = new OleDbConnection(DalCommon.ConnectionString); 
     _connection.Open(); 
     _unitOfWork = new UnitOfWork(_connection); 
    } 

    IDbConnection _connection = null; 
    UnitOfWork _unitOfWork = null; 

    public UnitOfWork UnitOfWork 
    { 
     get { return _unitOfWork; } 
    } 

    public void Dispose() 
    { 
     _unitOfWork.Dispose(); 
     _connection.Dispose(); 
    } 
} 

public sealed class UnitOfWork : IUnitOfWork 
{ 
    internal UnitOfWork(IDbConnection connection) 
    { 
     _id = Guid.NewGuid(); 
     _connection = connection; 
    } 

    IDbConnection _connection = null; 
    IDbTransaction _transaction = null; 
    Guid _id = Guid.Empty; 

    IDbConnection IUnitOfWork.Connection 
    { 
     get { return _connection; } 
    } 
    IDbTransaction IUnitOfWork.Transaction 
    { 
     get { return _transaction; } 
    } 
    Guid IUnitOfWork.Id 
    { 
     get { return _id; } 
    } 

    public void Begin() 
    { 
     _transaction = _connection.BeginTransaction(); 
    } 

    public void Commit() 
    { 
     _transaction.Commit(); 
     Dispose(); 
    } 

    public void Rollback() 
    { 
     _transaction.Rollback(); 
     Dispose(); 
    } 

    public void Dispose() 
    { 
     if(_transaction != null) 
      _transaction.Dispose(); 
     _transaction = null; 
    } 
} 

interface IUnitOfWork : IDisposable 
{ 
    Guid Id { get; } 
    IDbConnection Connection { get; } 
    IDbTransaction Transaction { get; } 
    void Begin(); 
    void Commit(); 
    void Rollback(); 
} 

Ora i repository devono accettare questo UnitOfWork in qualche modo. Scelgo Iniezione di dipendenza con Costruttore.

public sealed class MyRepository 
{ 
    public MyRepository(IUnitOfWork unitOfWork) 
    { 
     this.unitOfWork = unitOfWork; 
    } 

    IUnitOfWork unitOfWork = null; 

    //You also need to handle other parameters like 'sql', 'param' ect. This is out of scope of this answer. 
    public MyPoco Get() 
    { 
     return unitOfWork.Connection.Query(sql, param, unitOfWork.Transaction, .......); 
    } 

    public void Insert(MyPoco poco) 
    { 
     return unitOfWork.Connection.Execute(sql, param, unitOfWork.Transaction, .........); 
    } 
} 

E poi si chiamano in questo modo:

con la transazione:

using(DalSession dalSession = new DalSession()) 
{ 
    UnitOfWork unitOfWork = dalSession.UnitOfWork; 
    unitOfWork.Begin(); 
    try 
    { 
     //Your database code here 
     MyRepository myRepository = new MyRepository(unitOfWork); 
     myRepository.Insert(myPoco); 
     //You may create other repositories in similar way in same scope of UoW. 

     unitOfWork.Commit(); 
    } 
    catch 
    { 
     unitOfWork.Rollback(); 
     throw; 
    } 
} 

Senza transazione:

using(DalSession dalSession = new DalSession()) 
{ 
    //Your database code here 
    MyRepository myRepository = new MyRepository(dalSession.UnitOfWork);//UoW have no effect here as Begin() is not called. 
    myRepository.Insert(myPoco); 
} 

prega di notare che, UnitOfWork è more di DBTransaction.

Ulteriori dettagli sul deposito nel codice sopra possono essere trovati here.

Ho già postato questo codice here. Ma questa domanda mi sembra più pertinente per questo codice; quindi sto postando di nuovo invece del solo collegamento alla risposta originale.

+0

Questo è l'opposto di questo esempio dapper unitofwork 'https: // github.com/timschreiber/DapperUnitOfWork/blob/master/DapperUnitOfWork.Console/Program.cs'. Qui un'istanza di uow ha due o più repository all'interno di: –

+0

@JuniorM: Il codice nella mia risposta ottiene lo stesso risultato di Dependency Injection tramite Constructor.Come ho detto all'inizio di questa risposta, ho apportato alcune modifiche all'architettura originale. Grazie per aver notato però. –