【发布时间】:2018-08-23 09:57:04
【问题描述】:
我只是想更新客户对象的行业属性。为此,我使用存储库从数据库中检索客户端。这将导致我的行业(例如 id:149)被跟踪。
var client = await _clientRepository.GetAsync(request.ClientId, token);
ind = _db.ChangeTracker.Entries<Industry>().Count();
然后,我通过调用 SetIndustry 来更新行业,并使用 Id:149 的新行业(与之前相同)。
client.SetIndustry(new Industry(149));
ind = _db.ChangeTracker.Entries<Industry>().Count();
此时 EF Core 2.1 抛出异常。
System.InvalidOperationException: 'The instance of entity type 'Industry' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.
在此类中,我无法访问 DBContext,因此无法使用更改跟踪器。我想知道如何解决这个问题?
谢谢 赛博
【问题讨论】:
-
很难给你一个好的建议,因为你对这些“存储库”有自我限制。 EF 上下文为您提供了很好的控制 - 跟踪/不跟踪查询、是否预先加载等。存储库(反)模式可能适用于简单的事情,但肯定会因关系而失败。从 EF 的角度来看,您不应使用
new Industry(149),而应使用db.Find(149)或类似名称。或者将null分配给 nav 属性并设置暴露的显式 FK 属性。 -
实际上我们遵循 DDD 原则,我们正在使用这个存储库检索我们的聚合。同一个 repo 的 save 方法不仅仅是保存到数据库。这就是为什么我们必须这样做......
-
我在这里怀疑 DDD - 带有参数的构造函数、
SetIndustry方法等。这只是另一个问题来源。只是不要将域模型与持久性模型混合在一起——它们有不同的要求。或者换句话说,不要使用域模型作为存储模型。创建单独的模型,在需要的地方进行两者之间的映射。商店模型不应包含任何业务/领域逻辑 - 具有公共无参数构造函数和公共自动获取/设置属性的简单 POCO 类。没有方法。没有特殊的 getter/setter。没有未映射的东西。没有 OOP。
标签: entity-framework entity-framework-core change-tracking entity-framework-core-2.1