我们最近开始使用存储库模式和聚合根模式。当我使用EntityFramework跟踪更改时,这一切都非常有效,并且当我完成聚合工作时,我可以调用SaveChanges。
现在我的问题是我也希望将这个模式与我的mongodb一起使用,但从本质上讲,mongodb不支持更改跟踪。滚动我自己的变化跟踪似乎有点矫枉过正。
我的问题是我无法在关联聚合中对我的实体进行操作,然后使用存储库将其保存回mongodb。我只能使用ReplaceOneAsync
,这似乎不是最合适的,因为它是我正在创建的聊天,因此可能有来自不同客户端的多个写操作。
我想进行某种更改跟踪,这样我就可以使用指定的聚合调用存储库中的SaveChanges。
她是一些伪代码,试图解释我想要做的事情:
public abstract class BaseMongoRepository<TAggregate, TCollection> : IRepository<TAggregate> where TAggregate : BaseAggregateRoot, IMongoAggregate<TCollection>
{
private readonly IMongoCollection<TCollection> _mongoCollection;
protected BaseMongoRepository(IMongoCollection<TCollection> mongoCollection)
{
_mongoCollection = mongoCollection;
}
public async Task<bool> SaveAsync(TAggregate aggregate)
{
var state = aggregate.GetState();
foreach (var stateChange in state.Changes)
{
var change = stateChange.ToUpdateDefinition();
await _mongoCollection.UpdateOneAsync<TCollection>(aggregate.GetSelector(), change);
}
return true;
}
public TAggregate GetMongoAggregate(Expression<Func<TCollection, bool>> selector)
{
var state = _mongoCollection.AsQueryable().SingleOrDefault(selector);
return new AggregateWithSelector(state, selector);
}
}
GetMongoAggregate将在存储库的特定版本中实现,但这里是出于伪目的。
希望有人可以向我发送正确的方向,或者就如何对此进行建模提供一些建议。
答案 0 :(得分:1)
以下是我实施的一个简单示例(如果您需要真实示例,可以私下写信给我)
我有一个MongoDB集合:
public class TestCollection
{
public string Id { get; set; }
public string Name { get; set; }
}
我为集合制作了以下聚合根:
public class TestCollectionAggregateRoot : IAgregateRoot,
IHasObserver<IMongoObserver<TestCollection>>,
IHasSelector<IMongoSelector<TestCollection>>
{
private readonly IMongoSelector<TestCollection> _selector;
private readonly IMongoObserver<TestCollection> _observer;
private string _name;
public TestCollectionAggregateRoot(TestCollection root, IMongoSelector<TestCollection> selector, IMongoObserver<TestCollection> observer)
{
_selector = selector;
_observer = observer;
_name = root.Name;
}
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
_observer.OnPropertyChanged(x=>x.Name, _name);
}
}
}
public IMongoObserver<TestCollection> Observer => _observer;
public IMongoSelector<TestCollection> Selector => _selector;
}
其中
public interface IMongoObserver<TCollection>
{
void OnPropertyChanged<TField>(Expression<Func<TCollection, TField>> func, TField value);
UpdateDefinition<TCollection> Definition { get; }
}
public interface IMongoSelector<TCollection>
{
FilterDefinition<TCollection> Definition { get; }
}
IMongoObserver的简单实现:
public class MongoObserver<TCollection> : IMongoObserver<TCollection>
{
private volatile UpdateDefinition<TCollection> _definition;
public void OnPropertyChanged<TField>(Expression<Func<TCollection, TField>> func, TField value)
{
if (Definition != null)
{
_definition = Definition.Set(func, value);
}
else
{
_definition = Builders<TCollection>.Update.Set(func, value);
}
}
public UpdateDefinition<TCollection> Definition => _definition;
}
简单示例Repository.SaveAsync(不含InsertOneAsync)
public class Repository : IRepository<TestCollectionAggregateRoot>
{
private readonly IMongoCollection<TestCollection> _mongoCollection;
public Repository(IMongoCollection<TestCollection> mongoCollection)
{
_mongoCollection = mongoCollection;
}
public async Task<bool> SaveAsync(TestCollectionAggregateRoot aggregate)
{
var changes = aggregate.Observer.Definition;
var selector = aggregate.Selector.Definition;
await _mongoCollection.UpdateOneAsync(selector, changes);
return true;
}
}