背景:我有一个Person域对象。它是一个聚合根。我已经在下面列出了一部分课程。
我正在公开执行对象行为的方法。例如,要添加BankAccount,我有AddBankAccount()方法。我没有包括该类的所有方法,但足以说必须使用方法更新任何公共属性。
我将创建一个IPerson存储库来处理CRUD操作。
public interface IPersonRepository
{
void Save(Person p);
//...other methods
}
问题:在更新现有人员时,如何告知存储库需要更新哪些字段?例如,如果我向现有人员添加银行帐户,当调用repository.Save()时,如何将此信息传递给存储库?
在存储库中,很容易确定何时创建新人,但是当现有人员存在并且您更新该人员的字段时,我不确定如何将其传达给存储库。
我不想使用有关哪些字段更新的信息来污染我的Person对象。
我可以在存储库上使用单独的方法,例如.UpdateEmail(),AddBankAccount(),但这听起来有点矫枉过正。我想在存储库上使用一个简单的.Save()方法,它确定需要以某种方式更新的内容。
其他人如何处理这种情况?
我搜索了网络和stackoverflow但没有找到任何东西。我一定不能正确搜索,因为在DDD范例中持久化时,这似乎很简单。我也可以对DDD的理解有所了解: - )
public class Person : DomainObject
{
public Person(int Id, string FirstName, string LastName,
string Name, string Email)
{
this.Id = Id;
this.CreditCards = new List<CreditCard>();
this.BankAccounts = new List<BankAccount>();
this.PhoneNumbers = new List<PhoneNumber>();
this.Sponsorships = new List<Sponsorship>();
}
public string FirstName { get; private set; }
public string LastName { get; private set; }
public string Name{ get; private set; }
public string Email { get; private set; }
public string LoginName { get; private set; }
public ICollection<CreditCard> CreditCards { get; private set; }
public ICollection<BankAccount> BankAccounts { get; private set; }
public ICollection<PhoneNumber> PhoneNumbers { get; private set; }
public void AddBankAccount(BankAccount accountToAdd, IBankAccountValidator bankAccountValidator)
{
bankAccountValidator.Validate(accountToAdd);
this.BankAccounts.Add(accountToAdd);
}
public void AddCreditCard(CreditCard creditCardToAdd, ICreditCardValidator ccValidator)
{
ccValidator.Validate(creditCardToAdd);
this.CreditCards.Add(creditCardToAdd);
}
public void UpdateEmail(string NewEmail)
{
this.Email = NewEmail;
}
答案 0 :(得分:3)
有S#arp Architecture项目的Repository接口示例。它类似于PoEAA Data Mapper,因为它也用于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; }
}
如您所见,实体的特定属性没有更新方法。整个实体作为方法SaveOrUpdate
的参数提供。
当您的域实体的属性被更新时,您应该告诉您Unit of Work该实体是“脏”的并且应该保存到存储中(例如数据库)
您不应该使用有关更新字段的信息污染您的Person对象,但如果实体已更新,则需要跟踪信息。
可能有类DomainObject
的方法告诉'工作单位'实体是'新','脏'还是'删除'。然后您的UoW本身可能会调用正确的存储库方法 - “SaveOrUpdate”或“删除”。
尽管像NHibernate或EntityFramework这样的现代ORM框架有自己的“工作单元”实现,但人们倾向于为它们编写自己的包装/抽象。
答案 1 :(得分:0)
我正在做的解决此问题的方法是为我的域对象添加一个接口:
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();
}