存储库模式和聚合根模式。如何在存储库中创建SaveChanges?

时间:2016-10-31 16:40:46

标签: c# mongodb mongodb-.net-driver mongodb-csharp-2.0

我们最近开始使用存储库模式和聚合根模式。当我使用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将在存储库的特定版本中实现,但这里是出于伪目的。

希望有人可以向我发送正确的方向,或者就如何对此进行建模提供一些建议。

1 个答案:

答案 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;
    }
}