我们使用 MongoDb 作为我们应用程序的数据源,它是使用 cqrs 和事件源构建的。我们今天面临的问题是实现事件映射(非规范化)以读取数据库的最佳方法是什么。例如,我们有一个用户 MongoDb 集合,其中包含有关用户的所有信息。我们有这样的事件:
[Serializable]
public class PasswordChangedEvent : DomainEvent
{
private string _hashedPassword;
private string _salt;
public PasswordChangedEvent()
{
}
public PasswordChangedEvent(string hashedPassword, string salt, DateTime createdDate)
:base(createdDate)
{
HashedPassword = hashedPassword;
Salt = salt;
}
public string HashedPassword
{
private set { _hashedPassword = value; }
get { return _hashedPassword; }
}
public string Salt
{
private set { _salt = value; }
get { return _salt; }
}
}
并像阅读 DTO
public class User : BaseReportDataObject
{
public string Name { get; set; }
public string Email { get; set; }
public string Gender { get; set; }
public DateTime? BirthDate { get; set; }
public string HashedPassword { get; set; }
public string Salt { get; set; }
public string RestoreHash { get; set; }
public string OpenIdIdentifyer { get; set; }
}
我们当前使用事件更新文档的解决方案如下:我们有一些事件映射代码(BsonClassMap.RegisterClassMap 等)和更新代码:
MongoCollection.Update(Query<PasswordChangedEvent>.EQ(ev => ev.AggregateId, evnt.AggregateId),
Update<PasswordChangedEvent>
.Set(ev => ev.HashedPassword, evnt.HashedPassword)
.Set(ev => ev.Salt, evnt.Salt));
代码对我来说看起来有点丑陋和多余:使用所有 lambda 的东西,我们仍然需要显式地提供属性值。另一种方法是将 PasswordChangedEvent 替换为 User dto,因此我们不再需要事件映射:
MongoCollection.Update(Query<ReadDto.User>.EQ(u => u.Id, evnt.AggregateId),
Update<ReadDto.User>.Set(u => u.HashedPassword, evnt.HashedPassword));
那么问题又来了:有没有更好的方法来进行这种类型的映射?两种类型的对象(事件和 DTO)映射到同一个 mongo db 集合。