【问题标题】:Entities saved in incorrect order without exposed Foreign Keys以不正确的顺序保存的实体没有暴露的外键
【发布时间】:2011-08-15 22:06:46
【问题描述】:

当我尝试在 EF4 中保存具有父/子关系的实体时遇到问题。有时,孩子会被插入到父母之前——从参照约束的角度来看,这显然会导致问题。这两个表的结构如下:

OrderHeader
 - OrderID (PK)

OrderDetails
 - OrderID (PK)
 - DetailID (PK)

(还有更多的列,但它们并不重要)。

注意:我们不会在 OrderDetails.OrderID 上公开真正的外键,而是使用触发器来强制 Details 表的 OrderID 存在于 Header 表中。公开 FK 可能是一种快速的解决方案,但在我们的应用程序中,不允许对数据库进行此类更改 - 我们必须处理遗留代码等。

查看设计器生成的 .edmx 文件中的 XML,我注意到它在概念模型(CSDL 部分)中创建了一个关联集和关联 - 并且关联是使用引用约束设置的。但是,它不会在 SSDL 部分中创建 AssociateSet 或 Assocation。似乎只有当 FK 在数据库中公开时才会添加这些。对于我测试过的其他数据库(如 AdventureWorks 或 Northwind),在数据库中确实有真正的 FK,当我从数据库生成模型时,我看到 EDMX 在 SSDL 中包含 Association 和 AssociationSet 部分。

EF 似乎忽略了我们在模型 (CSDL) 中的关联,而只是按表名的字母顺序插入 - 所以在这种情况下我们运气不好,因为 OrderDetail 在 OrderHeader 之前排序(我们当然不会在我们的例子中有权重命名表)。如果我在 SSDL 部分手动添加相应的 AssociationSet 和 Association,则保存以正确的顺序发生(首先插入 Header,然后插入 Detail)。但是,无论何时我们执行“从数据库更新模型”,这些手动更改都会消失,因此这不是一个非常实用的解决方案。我曾考虑尝试在运行时动态地进行修复,但感觉要解决一些应该“正常工作”的事情需要付出很多努力。

我希望 EF 在订购插入时能够尊重 CSDL 中定义的引用约束和/或关联。

【问题讨论】:

  • 你们有一些可重复的样品吗?我这样做了几次,它很简单(在 EFv4 中)。
  • 它在没有 FK 的情况下工作?对我来说,它每次都打破。一位同事已在 EF 论坛上发布了完整的详细信息。您可以在这里看到一个可重现的案例:social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/… 最重要的事情似乎是 SSDL 部分中没有 Assocation 和 AssociationSet。当它适合您时,SSDL 部分是否有关联?
  • 当然......如果您没有特殊的触发器或没有分析 SQL,很容易错过“不正确”的行为。如果没有 FK,SQL Server 可能会让您在 Header 之前插入 Detail,但这是错误的行为。
  • 您的描述看起来很常见 FK association 在 SSDL 中没有对应的部分。我会在家里检查。
  • 顺便说一句。你在使用 EFv4 (.NET 4.0) 吗?您可能必须这样做,因为 .NET 3.5 中不存在引用约束。

标签: .net sql-server entity-framework .net-4.0 entity-framework-4


【解决方案1】:

我想我现在明白了这个问题。你在 SSDL 中根本没有关系。当 EF 生成 SQL 命令时,它仅使用来自 SSDL 的信息,因此它不知道 CSDL 中定义的实体之间的依赖关系。我稍后会验证它,但它看起来像是 EF 架构中的错误/设计缺陷。

你能做些什么来避免这个错误?在 SSDL 中手动定义关联集并使用一些 better tool(商业)与 EF 设计器一起工作并更新映射 - 或转到手动维护 EDMX,因为设计器仅适用于简单场景。

如果您与 Microsoft 有合作关系,您也可以将此行为作为错误报告给 MS Connect,或者将其作为支持票,但请注意,即使您获得解决方案也需要几个月的时间。

【讨论】:

  • 感谢您的信息。这证实了我所担心的——我们需要 SSDL 中的关联,以便 EF 将其考虑在内。我看过那个工具,它看起来很有希望,但仍然需要不断努力。我将探索制作我自己的 Visual Studio 插件来执行此操作。我们会看看情况如何。您找到的任何其他信息都会非常有帮助。
  • 即使 EF6 也有相同的...行为不端 :(
【解决方案2】:

在听到 Ladislav Mrnkka 的回答并且我自己没有找到一个“简单”的解决方案后,我想出了一个替代解决方案。这需要一些努力,但我认为最终结果是值得的。

我制作了一个使用 IModelTransofmrationExtension.OnBeforeModelSaved() 方法的 Visual Studio 扩展。在该方法中,您将获得 EDMX 文档作为 XDocument,您可以在保存之前根据需要对其进行操作。我利用这个机会扫描 CSDL 部分以查找 SSDL 中不存在的关联和关联集。然后我将它们复制到 SSDL 部分 - 在将实体/属性名称映射到具有 MSL 部分中的数据的表/列名称之后。

这有效地“欺骗”了 EF,使其认为我们的关联存在真正的外键,因此它以正确的顺序执行 INSERT。

唯一的缺点是我们团队中编辑模型的每个人都需要安装扩展程序 - 否则他们将无法获得生成的 FK 关联。幸运的是,我们只有几个人编辑模型,所以这很容易管理。

【讨论】:

    【解决方案3】:

    没有更改为实际使用 FK,不确定您是否可以开箱即用地做您想做的事情。您是否尝试过将整个插入(以正确的顺序并使用输出子句来取回 id,如果它们是第二个插入的标识)放入存储的过程中并让 EF 调用过程?

    【讨论】:

    • 我们考虑过手动对插入进行排序(通过存储过程或多次调用 SaveChanges),但我们有很多很多这样的表 - 有些表的关系更复杂(父>子>大child) 等,所以我们真的在努力避免这种情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-13
    • 2018-12-05
    • 1970-01-01
    • 2019-01-13
    • 1970-01-01
    相关资源
    最近更新 更多