Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Domain driven design 域驱动设计-如何处理aggregate根的部分更新_Domain Driven Design_Repository Pattern_Ddd Repositories_Aggregateroot - Fatal编程技术网

Domain driven design 域驱动设计-如何处理aggregate根的部分更新

Domain driven design 域驱动设计-如何处理aggregate根的部分更新,domain-driven-design,repository-pattern,ddd-repositories,aggregateroot,Domain Driven Design,Repository Pattern,Ddd Repositories,Aggregateroot,背景:我有一个Person域对象。它是一个聚合根。我已经包括了下面课程的一部分 我正在公开执行对象行为的方法。例如,要添加银行帐户,我有AddBankAccount()方法。我还没有包括该类的所有方法,但我只想说,任何公共属性都必须使用方法更新 我将创建一个IPerson存储库来处理CRUD操作 public interface IPersonRepository { void Save(Person p); //...other methods } 问题:当我们更新现有人员

背景:我有一个Person域对象。它是一个聚合根。我已经包括了下面课程的一部分

我正在公开执行对象行为的方法。例如,要添加银行帐户,我有AddBankAccount()方法。我还没有包括该类的所有方法,但我只想说,任何公共属性都必须使用方法更新

我将创建一个IPerson存储库来处理CRUD操作

public interface IPersonRepository
{ 
    void Save(Person p);
    //...other methods
}
问题:当我们更新现有人员时,如何告诉存储库哪些字段需要更新?例如,如果我向现有人员添加一个银行帐户,那么在调用repository.Save()时,如何将此信息传递给存储库

在存储库中,很容易确定何时创建一个新的人员,但是当一个现有人员存在并且您更新了该人员的字段时,我不确定如何将此信息传达给存储库

我不想用更新哪些字段的信息污染我的Person对象

我可以在存储库中使用单独的方法,如.updateMail()、AddBankAccount(),但这感觉有些过分了。我希望在存储库上有一个简单的.Save()方法,它确定需要以某种方式更新的内容

其他人是如何处理这种情况的

我在网上搜索过stackoverflow,但没有找到任何东西。我一定没有正确地搜索,因为在DDD范式中,这似乎是一件简单的事情。我对DDD的理解也可能有偏差:-)

公共类人物:DomainObject
{
公共人物(int-Id、string-FirstName、string-LastName、,
字符串名称,字符串(电子邮件)
{
这个.Id=Id;
this.CreditCards=新列表();
this.BankAccounts=新列表();
this.PhoneNumbers=新列表();
this.Sponsorships=新列表();
}
公共字符串名{get;private set;}
公共字符串LastName{get;private set;}
公共字符串名称{get;private set;}
公共字符串电子邮件{get;private set;}
公共字符串登录名{get;private set;}
公共ICollection信用卡{get;private set;}
公共ICollection银行帐户{get;private set;}
公共ICollection电话号码{get;private set;}
公共作废AddBankAccount(BankAccount accountToAdd,IBankAccountValidator bankAccountValidator)
{
bankAccountValidator.Validate(accountToAdd);
此.BankAccounts.Add(accountToAdd);
}
公共作废添加信用卡(信用卡添加,ICreditCardValidator ccValidator)
{
ccValidator.Validate(信用卡添加);
此.CreditCards.Add(creditCardToAdd);
}
public void UpdateEmail(字符串NewEmail)
{
this.Email=NewEmail;
}

有一个来自project的存储库接口示例。它与类似,因为它也用于CRUD操作

public interface IRepositoryWithTypedId<T, IdT>
{
    T Get(IdT id);    
    IList<T> GetAll();    
    IList<T> FindAll(IDictionary<string, object> propertyValuePairs);    
    T FindOne(IDictionary<string, object> propertyValuePairs);    
    T SaveOrUpdate(T entity);    
    void Delete(T entity);    
    IDbContext DbContext { get; }
}
公共接口IRepositoryWithTypedId
{
T-Get(IdT-id);
IList GetAll();
IList FindAll(IDictionary Property值对);
T FindOne(i字典属性值对);
T保存或更新(T实体);
无效删除(T实体);
IDbContext DbContext{get;}
}
如您所见,实体的特定属性没有更新方法。整个实体作为参数提供给方法
SaveOrUpdate

当域实体的属性正在更新时,您应该告诉您的域实体是“脏的”,应该保存到存储中(例如数据库)

您不应该用更新字段的信息污染Person对象,但若实体被更新,则需要跟踪信息

可能有类
DomainObject
的方法告诉“工作单元”实体是“新的”、“脏的”还是“删除的”。然后您的UoW本身可能会调用适当的存储库方法-“保存或更新”或“删除”


尽管现代ORM框架喜欢或有自己的“工作单元”实现,但人们倾向于为他们编写自己的包装/抽象。

我要解决这个问题,就是为我的域对象添加一个接口:

interface IDirtyTracker {
    bool IsDirty {get;}
    void MarkClean();
    void MarkDirty();
}
基本
DomainObject
类可以实现
IDirtyTracker
,然后存储库等可以使用
IsDirty
检查它是否脏或干净

在每个进行更改的setter中:

void SetValue() {
    this._value = newValue;
    this.MarkDirty();
}
这不会提供细粒度的检查,但这是一种避免在存储库级别进行一些不必要更新的简单方法

为了简化这一过程,可以添加一个
GetPropertiesToIncludeInDirtyCheck
方法,该方法将检索需要检查的属性列表

interface IDirtyTracker {
    IENumerable<Object> GetPropertiesToIncludeInDirtyCheck();
}
接口IDirtyTracker{
IENumerable GetPropertiesToIncludeInDirtyCheck();
}

感谢您的评论,非常感谢!不幸的是,我仍然不知道我的person对象如何使存储库知道已添加信用卡并需要保存,或者电子邮件已更新,只需要更新。我的person对象包含许多其他对象,但实际上它们映射到多个数据表s、 您是否使用任何ORM?您使用什么与存储库中的DB交互?通常有两个选项:第一->如果CreditCard是聚合根的子级,没有Person就没有意义,那么您应该更新/创建Person(数据库中的Persons表),然后更新CreditCards集合(数据库中的CreditCards表)使用PersonRepository.2->如果信用卡是一个没有人的实体,那么你应该使用自己的信用卡存储库创建/更新信用卡,然后使用PersonRepository创建/更新个人。再次感谢你的评论。在你的第一个场景中,我很难理解
interface IDirtyTracker {
    IENumerable<Object> GetPropertiesToIncludeInDirtyCheck();
}