【问题标题】:EF Core concurrency when using object graph使用对象图时的 EF Core 并发
【发布时间】:2021-12-28 19:11:20
【问题描述】:

我一直在研究 EF Core,并试图了解如何使用它来更新具有 DDD 的对象图。我的第一个测试在插入时运行良好,但现在我遇到了更新问题。

这个想法是让聚合根实体控制是否执行更新。在实践中,我需要确保 EF Core 在更改属于我的聚合的其他表之前始终检查“顶级实体”的版本字段。

但是,似乎 EF Core 将始终从更新“依赖表”开始,并且它只会在更新该实体或将其显式添加到时生成顶部的“更新”语句(具有版本并发检查)更新列表(例如:通过显式调用DbContextupdate 方法并将其传递给它)。

你们是怎么解决这个问题的?如果我使用 Dapper,我可能会在运行影响其他表的其他 SQL 指令之前尝试更新顶级实体(即使这可能意味着运行不会真正更新任何内容的更新)......通过这样做,我会确保完整的对象图在我的更新期间没有被其他用户更改(它包含在事务中)。

【问题讨论】:

  • Known problem,但没有简单的解决方案,尤其是。当一个图表有多个级别时不是。
  • 太令人失望了...我的印象是我不能将 int 用于版本字段,对吧?
  • 当然可以。只是 Rowversion 自动完成所有操作。
  • 谢谢。已经看到我正在接受的下一篇文章,因为我可以更改版本列类型。

标签: concurrency entity-framework-core aggregate domain-driven-design


【解决方案1】:

看看Confab solution on Github。这是其中的一小部分 - 一个示例 AggregateRoot 实现,可以帮助您解决问题:

public abstract class AggregateRoot<T>
{
    public T Id { get; protected set; }
    public int Version { get; protected set; }
    public IEnumerable<IDomainEvent> Events => _events;
    
    private readonly List<IDomainEvent> _events = new();
    private bool _versionIncremented;

    protected void AddEvent(IDomainEvent @event)
    {
        if (!_events.Any() && !_versionIncremented)
        {
            Version++;
            _versionIncremented = true;
        }
        
        _events.Add(@event);
    }

    public void ClearEvents() => _events.Clear();

    protected void IncrementVersion()
    {
        if (_versionIncremented)
        {
            return;
        }
        
        Version++;
        _versionIncremented = true;
    }
}

您需要在每次聚合更改时致电 AddEvent。请检查解决方案的其余部分。

您也可以尝试改进它。一种可能的选择是使用 EF ChangeTracker 在实体中搜索引发的域事件,然后增加聚合版本。

编辑

这里有一个article by Kamil Grzybek 值得一提。

【讨论】:

    猜你喜欢
    • 2021-02-26
    • 2016-06-21
    • 2020-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    相关资源
    最近更新 更多