警告我使用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书中,存在UnitOfWork
和IUnitOfWorkRepository
,其定义如下:
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的最简洁方法是什么?或者,这里的工作单元是不恰当的抽象,应留给其他用例吗?
答案 0 :(得分:3)
在DDD中,工作单元是业务流程本身。你有什么流行的反模式。无论如何,考虑到你的约束,最干净的事情是使Id属性可分配并将其设置在存储库中。
因此,您的项目将在repository.Add
方法中获取id。关于添加应该是不同操作的任务,您尝试在一个操作中执行太多操作。基本上,您正在使用“旧”'交易脚本(CRUD)方法,但使用DDD术语。
通常,您应该有一个添加项目的操作 - > ProjectCreated [事件] - > AddDefaultTasks。
UI也应该更基于任务,而不是一次做两件事。
我说,当db负责生成ID时,你无法真正做到正确的DDD。关键是,DDD并没有用一个神奇的配方修补蹩脚的代码库,它是关于自上而下的正确设计。但是你现在负责修补,所以你实际上不能做DDD。