We recently started using repository pattern and aggregate root pattern. This is all working super well when I am tracking the changes using EntityFramework, and I am able to call SaveChanges, when I am done with the work on my aggregate.
Now my problem is that I also want to use this pattern with my mongodb, but by nature, mongodb does not support change tracking. Rolling my own change tracking seems a bit of an overkill.
My problem is that I cannot do work on my entity in the associated aggregate, and then use the repository to save it back to mongodb. I can only do this if I use ReplaceOneAsync
, which does not seem to be the best fit, since it is a chat I am creating and therefor might have several write operations from different clients.
I would like to have some kind of change tracking that will allow me to call SaveChanges on the repository with the specified aggregate.
Her is some pseudo-code that tries to explain what I want to do:
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);
}
}
The GetMongoAggregate would be implemented in the specific versions of the repository, but is here for pseudo purpose.
Hopefully somebody can send me in the right direction or give me some advice on how to model this.