EF Core/SQL 根据条件加入不同的实体

Posted

技术标签:

【中文标题】EF Core/SQL 根据条件加入不同的实体【英文标题】:EF Core/SQL Join a different entity based on a condition 【发布时间】:2022-01-01 00:24:38 【问题描述】:

假设我有一个名为 Transactions 的表

交易有以下列

OrderId,
OrderType (Can be 0 = Sale or 1 = Purchase) <--- this can increase
Amount

现在我想根据 OrderType 获取相关数据 如果OrderType = 0 则从Sale Table else Join from Purchase Table 加入。

目前我正在做的是对数据库进行三次调用以从其他表中获取一些其他值(这有效,但从长远来看效率很低,因为 3 次调用在性能方面很糟糕)。

我的解决方案是使用 SQL 左连接

SELECT ap.*,
        coalesce(s.orderNo,p.orderNo) as orderNo
FROM apptransactions AS ap
LEFT JOIN sales AS s ON (ap.orderType = 0 and ap.orderId = s.id)
LEFT JOIN purchases AS p ON (ap.orderType = 1 and ap.orderId =  p.id);

如何将此查询转换为 EF Core?

【问题讨论】:

3 次调用在性能方面表现不佳 - 你有证据,还是假设? EF 无论如何都会进行左连接,如果它认为目标中可能有 0 行。您可以像正常一样使用它/不要想太多。就我个人而言,我认为我会将其拆分为 2 个查询(tran 包括 ordertype = 0 的销售,而 tran 包括 ordertype = 1 的采购)。但是代码对它的当前状态有一点味道;您在 tran 中的一列被 FK 输出到其他多个表。 orderId 真的应该叫salesIdOrPurchaseIdDependingOnOrderTypeId,当你添加第三个时,名称应该会变长.. 这表明数据建模出错了 您的架构不符合正常形式。您可能希望在TransactionsSales/Purchases 之间使用链接表。但很难说,因为我不知道您的完整数据集和用例。 @CaiusJard 你认为最好的方法是什么,添加多个列? (SaleId、PurchaseId、etcId、etcId),这不会导致行中有很多空值吗?因为让我们假设我有三列,并且在这三列中的每一行中只有一列有价值? 我正在做的是,这是一种事务日志,它在单个表中跟踪系统中的所有事务,我通过两列(OrderType,OrderId)和基于这些来区分它两列我也找到了这笔交易所属的地方,这可能不是最好的方法,但我愿意接受想法和建议。 【参考方案1】:

为什么你的查询不是这样的?

var results = context.Transactions.Select(t => 
    new 
     
        /* t.column list, there's no t.* in LINQ */, 
        OrderNo = t.OrderType == 0 ? t.Sale.OrderNo : t.Purchase.OrderNo
    );

让 EF 生成它需要的任何底层连接,关注获得所需的结果。

这也暗示了@caius 提到的内容。您的模型可能级别不够高或映射不正确。

【讨论】:

我正在做的是,这是一种事务日志,它在单个表中跟踪系统中的所有事务,我通过两列(OrderType,OrderId)和基于这些来区分它两列我也找到了这笔交易所属的地方,这可能不是最好的方法,但我愿意接受想法和建议。

以上是关于EF Core/SQL 根据条件加入不同的实体的主要内容,如果未能解决你的问题,请参考以下文章

如何根据 HTTP 响应中的条件返回不同的对象类型(.net 核心)

从PowerDesigner表字段的Name到EF实体类属性的Display Name(根据PowerDesigner生成EF实体类中文注释和验证元数据)

MsSql Mysql Ef Core DBFirst 根据数据库更新实体类

使用T4模板为EF框架添加实体根据数据库自动生成字段注释的功能

如何在 EF 中获取实体更改增量?

EF中更新操作 ID自增但不是主键 ;根据ViewModel更新实体的部分属性