2016-02-01 22 views
5

Il seguente codice sembra funzionare usando questo:PetaPoco + unità di lavoro + repository modello

var unitOfWorkProvider = new PetaPocoUnitOfWorkProvider(); 
var repository = new FakeRepository(); 
var fake = new Fake 
{  
    // etc. 
}; 

using (var uow = unitOfWorkProvider.GetUnitOfWork("BlaConnectionString")) 
{ 
    repository.Insert(uow, fake); 
    uow.Commit(); 
} 

che possono poi passare in un livello di servizio. Apprezzerei qualsiasi feedback per migliorare questo codice.

public interface IUnitOfWork : IDisposable 
{ 
    void Commit(); 
    Database Database { get; } 
} 

public interface IUnitOfWorkProvider 
{ 
    IUnitOfWork GetUnitOfWork(string connectionString); 
} 

public class PetaPocoUnitOfWorkProvider : IUnitOfWorkProvider 
{ 
    public IUnitOfWork GetUnitOfWork(string connectionString) 
    { 
     return new PetaPocoUnitOfWork(connectionString); 
    } 
} 

public interface IRepository<T> 
{ 
    void Insert(IUnitOfWork unitOfWork, T entity); 
    void Update(IUnitOfWork unitOfWork, T entity); 
    void Delete(IUnitOfWork unitOfWork, T entity); 
    T Fetch(IUnitOfWork unitOfWork, long uid); 
} 

public class PetaPocoUnitOfWork : IUnitOfWork 
{ 
    private readonly Transaction _petaTransaction; 
    private readonly Database _database; 

    public PetaPocoUnitOfWork(string connectionString) 
    { 
     _database = new Database(connectionString); 
     _petaTransaction = new Transaction(_database); 
    } 

    public void Dispose() 
    { 
     _petaTransaction.Dispose(); 
    } 

    public Database Database 
    { 
     get { return _database; } 
    } 

    public void Commit() 
    { 
     _petaTransaction.Complete(); 
    } 
} 

public class FakeRepository : IRepository<Fake> 
{ 
    public void Insert(IUnitOfWork unitOfWork, Fake entity) 
    { 
     unitOfWork.Database.Save(entity); 
    } 

    public void Update(IUnitOfWork unitOfWork, Fake entity) 
    { 
     unitOfWork.Database.Update(entity); 
    } 

    public void Delete(IUnitOfWork unitOfWork, Fake entity) 
    { 
     unitOfWork.Database.Delete(entity); 
    } 

    public FakeJobFact Fetch(IUnitOfWork unitOfWork, long uid) 
    { 
     return unitOfWork.Database.Fetch<Fake>("SELECT * FROM Fakes WHERE [FakeId] = @0", uid).FirstOrDefault(); 
    } 
} 

PS:

ho adattato il codice secondo @Plebsori risposta attuale:

public abstract class BaseRepository<T> 
{ 
    protected IDatabase Database 
    { 
     get 
     { 
     return UnitOfWork.Current; 
     } 
    } 

    public void Insert(T entity) 
    { 
     Database.Save(entity); 
    } 

    public void Update(T entity) 
    { 
     Database.Update(entity); 
    } 

    public void Delete(T entity) 
    { 
     Database.Delete(entity); 
    } 
} 

public interface IRepository<T> 
{ 
    void Insert(T entity); 
    void Update(T entity); 
    void Delete(T entity); 
    T Fetch(long uid); 
} 

public interface IUnitOfWork : IDisposable 
{ 
    void Commit(); 
    Database Database { get; } 
} 

public interface IUnitOfWorkProvider 
{ 
    IUnitOfWork GetUnitOfWork(string connectionString); 
} 

public class PetaPocoUnitOfWork : IUnitOfWork 
{ 
    private readonly Transaction _petaTransaction; 
    private readonly Database _database; 

    public PetaPocoUnitOfWork(string connectionString) 
    { 
     _database = new Database(connectionString); 
     _petaTransaction = new Transaction(_database); 
    } 

    public void Dispose() 
    { 
     UnitOfWork.Current = null; 
     _petaTransaction.Dispose(); 
    } 

    public Database Database 
    { 
     get { return _database; } 
    } 

    public void Commit() 
    { 
     _petaTransaction.Complete(); 
    } 
} 

public class PetaPocoUnitOfWorkProvider : IUnitOfWorkProvider 
{ 
    public IUnitOfWork GetUnitOfWork(string connectionString) 
    { 
     if (UnitOfWork.Current != null) 
     { 
     throw new InvalidOperationException("Existing unit of work."); 
     } 

     var petaPocoUnitOfWork = new PetaPocoUnitOfWork(connectionString); 
     UnitOfWork.Current = petaPocoUnitOfWork.Database; 
     return petaPocoUnitOfWork; 
    } 
} 

public static class UnitOfWork 
{ 
    [ThreadStatic] public static IDatabase Current; 
} 
+0

Potrebbe elaborare ciò che l'interfaccia "IDatabase" dovrebbe essere? Inoltre, eri contento di questo approccio? – Mathieu

risposta

6

Si può o non può piacere, ma ecco come ho rimosso il passaggio di unità di lavoro e l'unità di lavoro dall'interfaccia.

var unitOfWorkProvider = new PetaPocoUnitOfWorkProvider(); 
var repository = new FakeRepository(); 
var fake = new Fake 
{  
    // etc. 
}; 

using (var uow = unitOfWorkProvider.GetUnitOfWork("BlaConnectionString")) 
{ 
    repository.Insert(fake); 
    uow.Commit(); 
} 

Codice

public interface IUnitOfWorkProvider 
{ 
    IUnitOfWork GetUnitOfWork(string connectionString); 
} 

public static class UnitOfWork 
{ 
    [ThreadStatic] 
    public static IUnitOfWork Current { get; set; } 
} 

public class PetaPocoUnitOfWorkProvider : IUnitOfWorkProvider 
{ 
    public IUnitOfWork GetUnitOfWork(string connectionString) 
    { 
     if (UnitOfWork.Current != null) 
     { 
      throw new InvalidOperationException("Existing unit of work."); 
     } 
     UnitOfWork.Current = new PetaPocoUnitOfWork(connectionString); 
     return UnitOfWork.Current; 
    } 
} 

public interface IRepository<T> 
{ 
    void Insert(T entity); 
    void Update(T entity); 
    void Delete(T entity); 
    T Fetch(long uid); 
} 

public class PetaPocoUnitOfWork : IUnitOfWork 
{ 
    private readonly Transaction _petaTransaction; 
    private readonly Database _database; 

    public PetaPocoUnitOfWork(string connectionString) 
    { 
     _database = new Database(connectionString); 
     _petaTransaction = new Transaction(_database); 
    } 

    public void Dispose() 
    { 
     UnitOfWork.Current = null; 
     _petaTransaction.Dispose(); 
    } 

    public Database Database 
    { 
     get { return _database; } 
    } 

    public void Commit() 
    { 
     _petaTransaction.Complete(); 
    } 
} 

public abstract class BaseRepository<T> : IRepository<T> 
{ 
    protected IDatabase Db 
    { 
     get 
     { 
      return UnitOfWork.Current; 
     } 
    } 
} 

public class FakeRepository : BaseRepository<T> 
{ 
    public void Insert(Fake entity) 
    { 
     Db.Save(entity); 
    } 

    public void Update(Fake entity) 
    { 
     Db.Update(entity); 
    } 

    public void Delete(Fake entity) 
    { 
     Db.Delete(entity); 
    } 

    public FakeJobFact Fetch(long uid) 
    { 
     return Db.Fetch<Fake>("SELECT * FROM Fakes WHERE [FakeId] = @0", uid).FirstOrDefault(); 
    } 
} 
+0

Mi piace grazie. Sì, passare il tempo per tutto il tempo non sembra giusto. Semplicemente curioso - l'UnitOfWork.Current assicura che il repository utilizzi solo il flusso che fa parte dell'ambito di utilizzo? Grazie! – cs0815

+1

Aggiornamento dell'esempio di codice da lanciare se esiste un'altra unità di lavoro. Fermerà l'unità di lavoro annidata. Tuttavia, poiché la staticità è statica del thread, questo design implica che più thread avranno ciascuno il proprio ambito. – Plebsori

+0

qual è lo scopo di ThreadStatic se Current non è statico? – cs0815