【问题标题】:Entity Framework Navigation Property with Composite Foreign Key具有复合外键的实体框架导航属性
【发布时间】:2017-04-07 02:46:28
【问题描述】:

英孚 6.1.3.

我有一个域,其中包含许多“标题/项目”类型模式的实例,其中一个标题可以有许多项目(1 到多个),并且还有一个“当前”或“最新”项目。

这表示如下:

Header
    Guid Id
    Guid CurrentItemId
    Item CurrentItem 
    ICollection<Item> AllItems

Item
    HeaderId
    Id

Items 的 PK 始终是 HeaderID + ItemID。原因是,到目前为止,最常见的项目访问模式是列出与给定标头相关的所有项目,并且将 HeaderID 作为 PK/聚集索引的第一部分意味着我们通过聚集索引查找来获取该数据。

我们的问题是,当我们使用 CurrentItem 导航属性时,它只使用 ItemID 进行查找,这导致查询计划不太好。

我认为这是因为 EF 我们使用 CurrentItemId 来查找 CurrentItem 的约定。我的问题是,有没有办法让我通过映射 Header.Id,Header.CurrentItemId -> Item.HeaderId,Item.Id 来告诉 EF 始终为 CurrentItem 执行连接?

我相信这与此处描述的情况略有不同:composite key as foreign key

在我的情况下,我有一个一对一的映射,而不是一对一的映射,而且似乎没有适用于该场景的 WithforeignKey 方法。

【问题讨论】:

  • 我不确定它是否重复,因为您引用的帖子没有实体之间的列不匹配。在我的例子中,除了 CurrentVersionID 字段映射到 Item 实体中的 ID 字段之外,Header 的 ID 字段还需要映射到 Item.HeaderId 字段。也是一对一映射的情况,不是一对多映射,Item实体没有返回Header的nav属性。这可能是一个微小的差异,但它让我绊倒了。
  • 我们在我工作的地方做了一些非常相似的事情,但是使用整数并且没有这个问题。我在想 EF 可能会以不同的方式处理 guid,或者如果它在表上有一个唯一的约束,它正在尝试选择使用它。此外,guid 可能会导致一些碎片问题,我知道我们在 SQL Server 中遇到过这个问题。

标签: c# entity-framework entity-framework-6


【解决方案1】:

我们最终无法让 EF 以我们想要的方式生成 SQL - 因此我们编写了一个 db 命令拦截器来动态查找此连接的实例并重新编写连接以匹配我们设计的复合键。

我们将其配置为 DbContext 级别,如下所示:

    this.ModifyJoin<Item, Header>(
        (i) => new Header() { CurrentItemId = i.Id }, //What to find
        (i) => new Header() { CurerntItemId = i.Id, Id = i.HeaderId }); //What to replace with

此信息附加到上下文实例本身,因此当命令拦截器看到覆盖时,它会使用它们重新编写 SQL。

这在大多数情况下都可以正常工作,但也有一些情况 - 例如,当作为 LINQ 语句的一部分对 Item 表进行额外过滤时,EF 使用的别名规则变得过于复杂,无法在不编写代码的情况下遵循完整的 SQL 解析器。

对于我们的使用,这会导致大约 90% 的时间是理想的连接,这对我们来说已经足够了。

完成所有这些的代码并不难,但它太大了,无法放在这里。如果您想要一份副本,请添加评论,我会在 GitHub 上发布。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多