工作单元 + 存储库模式:业务事务概念的衰落

组合和是当今相当广泛使用的东西。正如 Martin Fowler 所说,使用的目的是形成一个商业交易,同时对存储库的实际工作方式一无所知(持续无知)。我已经回顾了许多实现;并忽略特定细节(具体/抽象类,接口,...),它们或多或少类似于以下内容:Unit of WorkRepository PatternUoW

public class RepositoryBase<T>
{
    private UoW _uow;
    public RepositoryBase(UoW uow) // injecting UoW instance via constructor
    {
       _uow = uow;
    }
    public void Add(T entity)
    {
       // Add logic here
    }
    // +other CRUD methods
}

public class UoW
{
    // Holding one repository per domain entity

    public RepositoryBase<Order> OrderRep { get; set; }
    public RepositoryBase<Customer> CustomerRep { get; set; }
    // +other repositories

    public void Commit()
    {
       // Psedudo code: 
       For all the contained repositories do:
           store repository changes.
    }
}

现在我的问题:

UoW公开公共方法 Commit 以存储更改。此外,由于每个存储库都有一个 共享实例 ,因此每个存储库都可以访问 UoW 上的方法。由一个存储库调用它会使所有其他存储库也存储其更改;因此,结果整个交易概念崩溃了:UoWRepositoryCommit

class Repository<T> : RepositoryBase<T>
{
    private UoW _uow;
    public void SomeMethod()
    {
        // some processing or data manipulations here
        _uow.Commit(); // makes other repositories also save their changes
    }
}

我认为这绝不能被允许。考虑到(业务事务)的目的,该方法应仅向启动业务事务(例如业务层)的人公开。令我惊讶的是,我找不到任何解决这个问题的文章。在所有这些中,都可以通过注入的任何存储库来调用。UoWCommitCommit

附言:我知道我可以告诉我的开发人员不要调用一个受信任的架构比受信任的开发人员更可靠!CommitRepository


答案 1

我同意你的关切。我更喜欢使用环境工作单元,其中打开工作单元的最外层函数是决定是提交还是中止的函数。调用的函数可以打开工作范围的单元,如果存在工作范围,则该单元会自动在环境 UoW 中登记,如果没有工作区,则创建一个新工作域。

我使用的 实现很大程度上受到工作原理的启发。使用环境/作用域方法也消除了依赖关系注入的需要。UnitOfWorkScopeTransactionScope

执行查询的方法如下所示:

public static Entities.Car GetCar(int id)
{
    using (var uow = new UnitOfWorkScope<CarsContext>(UnitOfWorkScopePurpose.Reading))
    {
        return uow.DbContext.Cars.Single(c => c.CarId == id);
    }
}

写入的方法如下所示:

using (var uow = new UnitOfWorkScope<CarsContext>(UnitOfWorkScopePurpose.Writing))
{
    Car c = SharedQueries.GetCar(carId);
    c.Color = "White";
    uow.SaveChanges();
}

请注意,仅当这是根(最顶层)作用域时,调用才会对数据库进行实际保存。否则,它将被解释为“同意投票”,即允许根范围保存更改。uow.SaveChanges()

的整个实现可在以下位置找到:http://coding.abel.nu/2012/10/make-the-dbcontext-ambient-with-unitofworkscope/UnitOfWorkScope


答案 2

使仓库成为 UoW 的成员。不要让您的存储库“看到”您的UoW。让 UoW 处理事务。


推荐