Lau*_*nSt 9 c# domain-driven-design ddd-repositories
我有一个真实的场景,是一个完美的领域模型设计.它是一个具有多个象限的字段,每个象限上具有不同的状态.所以我的聚合根是字段.现在我有一个重要的问题:我想拥有一个持久的ignorat域模型,我认为这是有道理的.那么我应该在哪里调用存储库方法的更新?不在域名模型中,对吧?那么当没有对象的更改跟踪代理并且不应该在实体中调用存储库时,如何在数据库中更新聚合根子实体?或者我误解了域模型模式?
我的问题清楚了吗?:)提前谢谢你最好的劳里
那么我应该在哪里调用存储库方法的更新?
在定型DDD体系结构中,存储库通常由应用程序服务调用.应用程序服务是一个类,它用作封装域的外观,并通过编排域对象,存储库和其他服务来实现域用例.
我不熟悉你的域名,但假设有是一个移动的使用情况State,从一个Quadrant在Field另一个.如你所说,Field是AR.所以你有一个FieldApplicationService参考FieldRepository:
public class FieldApplicationService
{
readonly FieldRepository fieldRepository;
public void ShiftFieldState(int fieldId, string quadrant, string state)
{
// retrieve the Field AR
var field = this.fieldRepository.Get(fieldId);
if (field == null)
throw new Exception();
// invoke behavior on the Field AR.
field.ShiftState(quadrant, state);
// commit changes.
this.fieldRepository.Update(field);
}
}
Run Code Online (Sandbox Code Playgroud)
应用程序服务本身非常薄.它没有实现任何域逻辑; 它只协调并设置执行域逻辑的阶段,包括访问存储库.所有依赖于您的域的代码(例如表示层或服务)都将通过此应用程序服务调用域功能.
存储库可以以各种方式实现.它可以是一个ORM,如NHibernate,在这种情况下,内置了更改跟踪,通常的方法是提交所有更改,而不是调用显式更新.NHibernate提供了一个工作单元,允许对多个实体的更改作为一个提交.
在您的情况下,如您所述,没有更改跟踪,因此需要显式调用更新,并由存储库实现来处理此问题.如果使用SQL Server作为数据库,则Update存储库上的方法可以简单地将a的所有属性发送Field到存储过程,该存储过程将根据需要更新表.
我的解决方案是聚合根将向外部事件处理程序引发一些事件。这些事件处理程序将调用存储库来更新数据库。您还需要一个 ServiceBus 来注册和分派事件。看我的例子:
public class Field: AggregateRoot
{
public UpdateField()
{
// do some business
// and trigger FieldUpdatedEvent with necessary parameters
....
// you can update some quadrants
// and trigger QuadrantsUpdatedEvent with necessary parameters
}
}
public class FieldEventHandlers: EventHandler
{
void Handle (FieldUpdatedEvent e)
{
repository.Update(e.Field);
}
}
public class QuadrantEventHandlers: EventHandler
{
void Handle (QuadrantsUpdatedEvent e)
{
repository.Update(e.Quadrant);
}
}
Run Code Online (Sandbox Code Playgroud)
聚合根(AR)在此处更新。使用消息驱动的体系结构,某处是命令处理程序,但一般来说,这是一种服务。该服务从存储库获取AR,调用相关方法,然后将AR保存回存储库。
AR不了解存储库,这与它无关。然后,存储库将所有AR修饰都保存为工作单位(即全部或全部不做)。回购如何做到这一点,这取决于您如何确定持久性策略。
如果您使用事件源,则AR会生成事件,并且Repo将使用这些事件来保持AR状态。如果您采用更通用的方法,那么AR应该在某个位置公开状态数据作为属性。这就是所谓的纪念图案。存储库一次提交就保留该数据。
可以肯定的是:在处理Domain对象时,永远不要考虑持久性细节。那是不要将域耦合到ORM或某些数据库特定的东西。
“应用程序代码”应调用存储库。如何托管应用程序代码是基础架构关注的问题。关于如何托管应用程序代码的一些示例是WCF服务,作为Winforms / WPF应用程序或在Web服务器上。
存储库实现负责跟踪对聚合根及其子实体的更改,并将其保存回数据库。
这是一个例子:
领域项目
public DomainObject : AggregateRootBase //Implements IAggregateRoot
{
public void DoSomething() { }
}
public IDomainObjectRepository : IRepository<DomainObject>, IEnumerable
{
DomainObject this[object id] { get; set; }
void Add(DomainObject do);
void Remove(DomainObject do);
int IndexOf(DomainObject do);
object IDof(DomainObject do);
IEnumerator<DomainObject> GetEnumerator();
}
Run Code Online (Sandbox Code Playgroud)
实施项目
public SqlDomainObjectRepository : List<DomainObjectDataModel>, IDomainObjectRepository
{
//TODO: Implement all of the members for IDomainObjectRepository
}
Run Code Online (Sandbox Code Playgroud)
应用项目
public class MyApp
{
IDomainObjectRepository repository = //TODO: Initialize a concrete SqlDomainObjectRepository that loads what we need.
DomainObject do = repository[0]; //Get the one (or set) that we're working with.
do.DoSomething(); //Call some business logic that changes the state of the aggregate root.
repository[repository.IDof(do)] = do; //Save the domain object with all changes back to the db.
}
Run Code Online (Sandbox Code Playgroud)
如果您需要将更改以事务方式对多个聚合根进行事务处理,以便完全或完全不进行更改,则应查看“工作单位”模式。
希望这有助于澄清问题!
| 归档时间: |
|
| 查看次数: |
3785 次 |
| 最近记录: |