存储库模式和聚合根模式。如何在存储库中进行 SaveChanges?
Repository pattern and aggregate root pattern. How to make SaveChanges in repository?
我们最近开始使用存储库模式和聚合根模式。当我使用 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 将在存储库的特定版本中实现,但此处用于伪目的。
希望有人能告诉我正确的方向或给我一些关于如何建模的建议。
这是我实现的一个简单例子(如果需要真实例子可以私信我)
我有一个 MongoDB collection:
public class TestCollection
{
public string Id { get; set; }
public string Name { get; set; }
}
我为 collection 创建了以下聚合根:
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;
}
}
我们最近开始使用存储库模式和聚合根模式。当我使用 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 将在存储库的特定版本中实现,但此处用于伪目的。
希望有人能告诉我正确的方向或给我一些关于如何建模的建议。
这是我实现的一个简单例子(如果需要真实例子可以私信我)
我有一个 MongoDB collection:
public class TestCollection
{
public string Id { get; set; }
public string Name { get; set; }
}
我为 collection 创建了以下聚合根:
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;
}
}