【发布时间】:2021-02-13 08:39:19
【问题描述】:
上下文
我正在尝试自己的 DDD 架构。与我见过的其他项目的主要区别在于,我没有使用我的域模型作为数据实体,而是我有单独的模型,我称之为商店,它们从域模型映射并表示数据库的状态。
如果您不熟悉DDD,其想法是将核心业务逻辑与应用程序的其他元素(例如数据库)完全解耦。为了实现这一点,我定义了包含业务逻辑和验证的域模型,然后定义了实体模型,它们表示与域模型相同的状态(业务和验证逻辑条带化),但也表示 EF 特定的关系属性。
问题
EF 操作适用于更简单的操作。假设我们有一个竞赛,它可以包含多个试验。
伪代码示例:
contest = new Contest
contest.Add(new Trial(1))
contest.Add(new Trial(2))
data.Save(contest) // performs mapping to ContestEntity and calls dbContext.Add
// So far so good
contestWithTrials = data.Get() // contest comes with 2 Included Trials
contestWithTrials.Add(new Trial(3))
data.Save(contestWithTrials) // performs mapping, calls dbContext.Update and tries to save but fails.
错误是:
无法跟踪实体类型“Trial”的实例,因为已在跟踪另一个具有键值“{Id: 1}”的实例
或
试图更新或删除商店中不存在的实体
由于某种原因,映射混淆了 EF,它试图重新创建已经存在的 Trial,但我不明白为什么 - 我可以看到在调用 SaveChanges 之前在 DbSet.Local 中正确添加了实体,但是它仍然会抛出。
我已经建立了一个 PoC 分支here。根据 Progrman 的建议,它是一个控制台应用程序,具有最少的可重现示例。由于设置需要几个包,我认为最好在一个 repo 中而不是单个文件中。
【问题讨论】:
-
不清楚问题是什么或您要解决什么问题。请edit您的问题包含您拥有的完整源代码作为minimal reproducible example,其他人可以编译和测试。 StackOverflow 上有很多问题涉及诸如“实体类型的实例......无法跟踪,因为另一个具有键值的实例”之类的错误。
-
@Progman 感谢您的提示,同时将代码库简化为可能的最简单配置,我已经缩小了问题的范围。我仍然无法弄清楚,但我完全重写了我的问题并提供了代码示例,尽管是在一个 repo 中。
-
请不要将 MCVE 添加到外部站点,将其添加到您的问题本身。还要保持“最小”,这表明您遇到的问题。
-
@Progman 我不明白。为什么你更喜欢有一个大的复制粘贴,而不是简单地克隆一个 repo?复制粘贴也不起作用,因为您需要安装 Nuget 包。我最好走这条路。正如我之前所说 - 它已经是“最小的”。我从纯控制台应用程序归零并添加了组件,直到我设法模拟了同样的问题。
-
该问题与 AutoMapper 有关,您可能需要查看其他问题,例如 stackoverflow.com/questions/41482484/…、stackoverflow.com/questions/50459427/… 或 stackoverflow.com/questions/48359363/…,这些问题解释了更新子实体的问题。
标签: c# asp.net-core entity-framework-core domain-driven-design