使用 EF-Core 继承类之间的意外连接

问题描述 投票:0回答:1

当一个类从 EF-Core 的另一个类继承时,这会导致不应存在关系的映射之间自动映射。

我使用的是 EFCore 版本 6.0.1

所以我有两个表,分别称为“Cards”和“CardsHistory”。 CardsHistory 是一个历史记录表,包含 Cards 中的所有列,但还有一些额外的列,例如“HistoryId”和“DateActive”。我在 EF 中将其表示为 CardsHistory 实体,它继承了 Cards 实体,并带有一些额外的字段。

卡片看起来像下面的类。注意,这个类中没有任何地方引用 CardsHistory

public class Card{
  int id {get;set;}
  ...
  int cost {get;set;}
}

CardsHistory 看起来像这样

public class CardHistory: Card {
  int HistoryId
  DateTime DatesActive
}

然后将实体放入数据库上下文中的数据库集中。

当我对卡进行任何查询时,会发生意外行为。目前我的数据库中只有一张 ID 为“1”的卡。它已被修改过一次,因此其历史表中有两个条目。 如果我执行以下查询

dbContext.Cards.Where(c=>c.id==1).toList()
我希望只有一张卡。我最终得到两张卡,一张对应卡历史表中的每个条目。此行为随给定卡的条目数量而变化。意思是,卡片修改 4 次将会退回 4 张卡片,而不是我期望退回的唯一一张卡片。

我设法使用下面列出的意外鉴别器块来追踪发送到数据库的查询。

-- @__p_1='150'
-- @__p_0='0'
SELECT t."Id", ..., t."Cost"
FROM (
    SELECT c."Id", ... ,  c0."HistoryId", CASE
        WHEN (c0."Id" IS NOT NULL) THEN 'CardHistory'
    END AS "Discriminator"
    FROM "Cards" AS c
    LEFT JOIN public_history."CardsHistory" AS c0 ON c."Id" = c0."Id"
    WHERE c."InventoryId" = 30001
    ORDER BY c."InventoryId"
    LIMIT @__p_1 OFFSET @__p_0
) AS t
LEFT JOIN "Products" AS p0 ON t."ProductId" = p0."Id"
LEFT JOIN "Users" AS u ON t."PurchasedById" = u."Id"
ORDER BY t."InventoryId"

我可以通过从 dbContext 中删除 CardHistory 来恢复原来的预期行为。

我无法判断我是否违反了 EFcore 的约定,或者在定义这种关系时是否犯了 OO 错误。关于堆栈溢出和其他编程网站的其他帖子指出这是

的某种组合
  1. TBT vs TBH
  2. 延迟加载
  3. 正确配置FK关系

该关系不是 FK 关系,因此我永远无法实现第 2 点或第 3 点。我尝试配置 TBT 而不是下图中的 TBH,但这在输出中没有产生任何差异。 Card 和 CardHistory 的模型构建器定义图像

c# .net entity-framework
1个回答
0
投票

我会首先尝试定义 FK 关系。这样一张卡就有了历史条目的集合。

您还可以尝试在历史类型上配置

.HasBaseType((Type)null)
,以便 EF 不会推断那里的层次结构。

© www.soinside.com 2019 - 2024. All rights reserved.