我正在尝试在我的项目中使用工作单元和存储库。 然后让我思考如何用它实现交易。
目前这是我打算做的事情:
public class UnitOfWork : IUnitOfWork
{
private readonly IDbFactory databaseFactory;
private adminBoContext dataContext;
private DbContextTransaction _transaction;
private Repository<a> repoA;
....
private Repository<x> repoX;
public UnitOfWork(IDbFactory databaseFactory)
{
this.databaseFactory = databaseFactory;
_transaction = dataContext.Database.BeginTransaction();
}
protected Context DataContext
{
get { return dataContext ?? (dataContext = databaseFactory.Get()); }
}
public void Commit()
{
try
{
_transaction.Commit();
}
catch (Exception ex)
{
_transaction.Rollback();
}
}
}
然后我也遇到了SocialGoal project这样的例子 工作单元(但内部没有存储库)和看起来像的单独存储库有自己的上下文实例
public class UnitOfWork : IUnitOfWork
{
private readonly IDatabaseFactory databaseFactory;
private SocialGoalEntities dataContext;
public UnitOfWork(IDatabaseFactory databaseFactory)
{
this.databaseFactory = databaseFactory;
}
protected SocialGoalEntities DataContext
{
get { return dataContext ?? (dataContext = databaseFactory.Get()); }
}
public void Commit()
{
DataContext.Commit();
}
}
public abstract class RepositoryBase<T> where T : class
{
private SocialGoalEntities dataContext;
private readonly IDbSet<T> dbset;
protected RepositoryBase(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
dbset = DataContext.Set<T>();
}
protected IDatabaseFactory DatabaseFactory
{
get;
private set;
}
protected SocialGoalEntities DataContext
{
get { return dataContext ?? (dataContext = DatabaseFactory.Get()); }
}
public virtual void Add(T entity)
{
dbset.Add(entity);
}
我现在真的很困惑应该如何实现工作单元和存储库,因为据我所知,工作单元将成为所有存储库访问权限的主要门。
如果有人能够对这个工作单元和存储库实现有所了解,我将非常感激。
非常感谢你。
答案 0 :(得分:3)
UnitOfWork应该开始并完成交易。这直接源于其名称。
我在原始代码中会改变的是,您的UoW知道太多的存储库。如果再添加一个存储库,则必须更改UoW类,这是一件坏事。
您需要将UoW实例注入通用存储库构造函数,并使用存储库中的UoW上下文。
使用IoC容器时,您需要确保您的存储库和UoW具有匹配的生命周期范围。
答案 1 :(得分:1)
应该只在您的工作单元类中创建并将相同的 dataContext传递到您的存储库中,还应该在您的单元中提交或回滚dataContext工作。
您的存储库不应创建自己的dataContext,而应使用工作单元中传入的dataContext。有了它,我们可以跨存储库协调事务。
您问题的示例代码可以像这样实现:
public class UnitOfWork : IUnitOfWork
{
private readonly IDbFactory databaseFactory;
private adminBoContext dataContext;
private DbContextTransaction _transaction;
private Repository<a> repoA;
private Repository<x> repoX;
public UnitOfWork(IDbFactory databaseFactory)
{
this.databaseFactory = databaseFactory;
_transaction = DataContext.Database.BeginTransaction();
//pass the same context to your repositories
repoA = new Repository<A>(DataContext);
repoX = new Repository<X>(DataContext);
}
protected Context DataContext
{
get { return dataContext ?? (dataContext = databaseFactory.Get()); }
}
public void Commit()
{
try
{
_transaction.Commit();
}
catch (Exception ex)
{
_transaction.Rollback();
}
}
}
旁注:
您的工作单元应实施IDisposable
,以确保即使我们忘记明确地处理上下文,也始终处理上下文。实现更多这样的代码:
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
dataContext.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
您的代码应类似于:
public class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly IDbFactory databaseFactory;
private adminBoContext dataContext;
private DbContextTransaction _transaction;
private Repository<a> repoA;
private Repository<x> repoX;
public UnitOfWork(IDbFactory databaseFactory)
{
this.databaseFactory = databaseFactory;
_transaction = DataContext.Database.BeginTransaction();
//pass the same context to your repositories
repoA = new Repository<A>(DataContext);
repoX = new Repository<X>(DataContext);
}
protected Context DataContext
{
get { return dataContext ?? (dataContext = databaseFactory.Get()); }
}
public void Commit()
{
try
{
_transaction.Commit();
}
catch (Exception ex)
{
_transaction.Rollback();
}
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
dataContext.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
您的存储库:
public abstract class RepositoryBase<T> : IRepository<T>
where T : class
{
protected DbSet<T> Set { get; set; }
protected Context Context { get; private set; }
protected RepositoryBase(Context dataContext)
{
Context = dataContext;
Set = Context.Set<T>();
}
答案 2 :(得分:0)
感谢Alexey和Khanh,
根据您的建议,我尝试修改我的工作单位,如下所示:
public class UnitOfWork : IUnitOfWork
{
private readonly IDbFactory databaseFactory;
private Context dataContext;
private DbContextTransaction _transaction;
public UnitOfWork(IDbFactory databaseFactory)
{
this.databaseFactory = databaseFactory;
}
public IDbContext BeginTransaction<T>()
{
if (_dataContext == null)
{
_dataContext = _databaseFactory.Get<T>();
_transaction = _dataContext.BeginTransaction();
}
return _dataContext;
}
public void Commit()
{
try
{
_transaction.Commit();
}
catch (Exception ex)
{
_transaction.Rollback();
throw ex;
}
}
}
我在实例化存储库时采用了工作单元,如下所示:
public abstract class RepositoryBase<T> : IRepository<T>
where T : class
{
protected DbSet<T> Set { get; set; }
protected Context Context { get; private set; }
protected RepositoryBase(IDbContext context)
{
Context = context;
Set = Context.Set<T>();
}
//CRUD functions
public void Save()
{
Context.SaveChanges();
}
}
@Alexey,这就是将UOW注入存储库的意思吗?
@Khanh,现在我将上下文直接传递到存储库并将Save方法添加到其中,因此它可以保存(对于我需要新插入的实体的情况)但是仍然在事务中包装。
谢谢