【发布时间】:2013-11-07 06:41:03
【问题描述】:
更改自: “使用实体框架(和其他 ORM)进行域模型验证。一些数据在数据库中,一些在内存中。”
最初我认为用 EF 实现 UoW 是一件容易的事。但事实证明这要复杂得多。
当业务逻辑(无论它位于何处)向存储库请求实体时,它不仅应该在数据库中搜索,还应该在本地缓存中搜索。存储库不应返回实体,以防它在当前 UoW 中被标记为删除,但它仍然存在于存储中。
带来复杂性的是部分图物化。当我们忘记持久性并假装一切都存在于内存中时,毫无疑问:加载一切,根据需要更改它,然后将结果更改写入 db。尽可能简单。
添加更多细节:
身份验证消息处理程序设置 Principal。
在我的 BL 深处,我需要检查当前经过身份验证的用户是否可以执行该操作。
每个角色都有与之相关的动作。所以我需要找到所有角色的动作并检查用户是否在角色中。但是,有可能在处理请求期间用户已从角色中删除。有关删除(或添加)的信息保存在 UoW 内部,但尚未保存。因此,如果我的检查逻辑只询问 DB,它会得到与工作流程不一致的答案。
可能是我错误地设置了 UoW 的边界,它不应该跨越单独的 BL 操作:
- 从角色中删除用户 - 更改到 DB
- 检查用户角色 - 从数据库中获取状态
虽然 BL 可以在每次写入 DB 时进行嵌套调用。所以我觉得让客户定义UoW的“大小”是可以的。
Fowler describing UoF 说:
您可以在每次更改对象模型时更改数据库, 但这会导致大量非常小的数据库调用,最终导致 很慢。此外,它要求您进行交易 对整个交互开放,如果你有一个 跨越多个请求的业务事务。情况是 更糟糕的是,如果你需要跟踪你读过的对象,所以你 可以避免不一致的读取。
但行为可能需要一系列对象更改。并且每次更改都必须知道当前状态 - 先前更改后尚未存储在 DB 中的状态。
问题的原始措辞:
我对使用实体框架实现的存储库和工作单元模式有些困惑。
首先,我允许我的模型在 UnitOfWork 的 Commit() 阶段之前处于无效状态。
最简单的例子就是移动和重命名文件语义。
如果您需要将file1 移动到Dir2 并将其重命名为file2,如果您将移动 和重命名 操作。Dir1 或 Dir2 中存在命名冲突。
所以我认为允许模型暂时具有无效状态是合理的。
现在我的问题的本质:
我的业务模型有一个规则,要求分析所有相关实体。
我将验证逻辑放在逻辑上包含所有这些项目的父实体中,因此负责施加和检查约束。而且我还想检查唯一性约束。
这听起来可能有点偏执,但在这种情况下,即使不使用数据库,我也可以通过单元测试轻松检查我的逻辑。
然而,在 EF 开始验证过程时,“未来”系统的状态由当前上下文(添加、删除、修改项)和未具体化到内存中并保留在数据库中的部分(更不用说并发)定义。 (绝对不能将所有实体加载到内存中)。
这需要我的存储库非常详细,以考虑分布式状态的事实。我发现这不是一项简单的任务。
我想知道其他人是如何解决这个问题的。可能有更好的方法来解决这个问题。
【问题讨论】:
-
您所描述的内容被称为“最终一致性”或“基础”。这是关于一致性的另一种观点,它没有“事务”或“ACID”那么严格。谷歌搜索其中一些术语应该可以帮助您找到答案,因为解决方案对您当前的方法非常主观(即您是否在做 CQRS?)。
-
好吧'我更多的是研究 DDD 部分而不是积极的实施。一旦我接近持久性无知,存储库、UoW 和类似 DDD 的东西就会变得非常模糊。
标签: .net entity-framework validation domain-driven-design ddd-repositories