如何在工作单元中处理数据库生成的id值

时间:2015-08-21 20:12:33

标签: c# sql-server domain-driven-design ddd-repositories

警告我使用SQL Server 2008 R2作为持久性框架。我无法改变这一点。我正在使用Micro-ORM来实现持久性。我也没有改变这个的选择。第三,我没有选择将表标识列更改为guids。它们必须保持整数。

我想要创建的聚合是一个包含一些任务的项目。我想将它持久化到两个表,一个用于父项目,另一个用于任务,由父项目id链接。很简单。显然,表结构是一个持久性细节,我想不在域模型之外。一旦我坚持这一点,我想将项目的id发送回用户,以便他们可以导航到新创建的项目。

public class CreateNewProjectRequest
{
    public int InterestingInteger { get; set; }
    public string MoreDataNeededForRequest { get; set; }
}

public CreateProjectApplicationService
{
    private readonly IUnitOfWork uow;

    public CreateProjectApplicationService(IUnitOfWork uow)
    {
        this.uow = uow;
    }

    public int CreateNewProject(CreateNewProjectRequest request)
    {
        var project = ProjectAggregate.CreateFrom(request);
        var projectRepository = new ProjectRepository(uow);
        projectRepository.Add(project);
        projectRepository.Save(project);
        //db transaction commits
        uow.Commit();
    }
}

引用有关此主题的几个资源(Vaughn Vernon的DDD书和最新的Wrox DDD书籍模式,原理和域驱动设计实践),我看到存储库负责聚合根的持久性。存储库接口存在于域模型中。

在Wrox DDD书中,存在UnitOfWorkIUnitOfWorkRepository,其定义如下:

public interface IUnitOfWork
{
    void RegisterAmended(IAggregateDataModel entity, IUnitOfWorkRepository unitofWorkRepository);
    void RegisterNew(IAggregateDataModel entity, IUnitOfWorkRepository unitofWorkRepository);
    void Commit();
    void Clear();
}

public interface IUnitOfWorkRepository
{
    void PersistCreationOf(IAggregateDataModel entity);
    void PersistUpdateOf(IAggregateDataModel entity);
    void PersistDeleteOf(IAggregateDataModel entity);
}

public class ProjectRepository : IProjectRepository, IUnitOfWorkRepository
{
    //Simplified for example's sake, I didn't implement all of IUnitOfWorkRepository
    private readonly IUnitOfWork uow;

    public ProjectRepository(IUnitOfWork uow)
    {
        this.uow = uow;
    }

    public void Add(Project project)
    {
        unitOfWork.RegisterNew(project, this);
    }

    public void PersistCreationOf(IAggregateDataModel entity)
    {
        //Persist changes via micro ORM -- new id is available
    }
}

commit的实现创建了一个事务并将其保留。

我遇到的问题是,当调用Commit()方法将事务持久化到数据存储时,我有一个在该过程中创建的新ID。我知道CreateProjectApplicationService可能触及多个聚合(在我的情况下它还没有...),因此工作单元实现在这里管理事务,因此数据存储处于一致状态。

我不能简单地从数据库中播种id。我想使用scope_identity()来获取db生成的id,因为它是一个自动增量列。

获得这个新插入ID的最简洁方法是什么?或者,这里的工作单元是不恰当的抽象,应留给其他用例吗?

1 个答案:

答案 0 :(得分:3)

在DDD中,工作单元是业务流程本身。你有什么流行的反模式。无论如何,考虑到你的约束,最干净的事情是使Id属性可分配并将其设置在存储库中。

因此,您的项目将在repository.Add方法中获取id。关于添加应该是不同操作的任务,您尝试在一个操作中执行太多操作。基本上,您正在使用“旧”'交易脚本(CRUD)方法,但使用DDD术语。

通常,您应该有一个添加项目的操作 - > ProjectCreated [事件] - > AddDefaultTasks。

UI也应该更基于任务,而不是一次做两件事。

我说,当db负责生成ID时,你无法真正做到正确的DDD。关键是,DDD并没有用一个神奇的配方修补蹩脚的代码库,它是关于自上而下的正确设计。但是你现在负责修补,所以你实际上不能做DDD。