[英]How do I deal with database generated id values in a unit of work
请注意,我使用SQL Server 2008 R2作为持久性框架。 我没有更改此选项。 我正在使用Micro-ORM进行持久化。 我也没有选择更改此选项。 第三,我没有选择将表标识列更改为向导。 它们必须保留为整数。
我要创建的聚合是一个有一些任务的项目。 我想将其保存到两个表,一个表与父项目,另一个与任务,由父项目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()
方法将事务持久化到数据存储区时,我有一个在该过程中创建的新ID。 我知道CreateProjectApplicationService
可能涉及多个聚合(在我看来,它还没有...),因此工作单元实现在此处管理事务,因此数据存储处于一致状态。
我不能只是从数据库中播种ID。 我想使用scope_identity()
获取数据库生成的ID,因为它是一个自动递增的列。
获得此新插入的ID的最干净的方法是什么? 或者,这里的工作单元是不适当的抽象,应该留给其他用例吗?
在DDD中,工作单元是业务流程本身。 您所拥有的是一种流行的反模式。 无论如何,考虑到您的约束,最干净的事情是使Id属性可分配并在存储库中进行设置。
因此,您的项目将在repository.Add
方法中获取ID。 关于添加任务,这应该是一项不同的操作,您正在尝试在一个操作中做太多事情。 基本上,您使用的是“旧的”事务处理脚本(CRUD)方法,但带有DDD术语。
通常,您应该对添加项目执行一个操作-> ProjectCreated [event]-> AddDefaultTasks。
用户界面还应该更多地基于任务,而不是一次执行两种不同的操作。
我想说,当数据库负责生成ID时,您实际上不能做适当的DDD。 关键是,DDD并不是用魔术方法修补糟糕的代码库,而是要自上而下地进行适当的设计。 但是您现在负责打补丁,因此您实际上无法执行DDD。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.