【问题标题】:Translate SQL to LINQ with OR statements in a JOIN使用 JOIN 中的 OR 语句将 SQL 转换为 LINQ
【发布时间】:2013-08-24 07:03:45
【问题描述】:

我有一个非常基本的 SQL 连接语句,我似乎不知道如何使它在 LINQ 中工作。它在 JOIN 中使用 OR 语句,我在网上找到了在 JOIN 中使用 AND 的代码,但在我的情况下对 OR 没有任何帮助。

这里是 SQL:

SELECT *
FROM Proposals AS a
LEFT JOIN Proposal_Minions AS b
    ON a.ID = b.Proposal_ID
LEFT JOIN Users AS c
    ON (a.PI_User_ID = c.ID) OR (a.Creator_User_ID = c.ID) OR (b.User_ID = c.ID)
WHERE c.Account = 'myname'

任何帮助将不胜感激。

【问题讨论】:

  • 我认为不可能使用 LINQ。
  • 必须是 LINQ 吗?如果需要(通常是为了更好的性能),您可以对 DBconext 执行原始 SQL。
  • 使用 LINQ 而不是 SQL 是一种不好的代码气味。即使可能,您也不应该使用 LINQ。 EF 或 Linq to SQL 是 ORM,而不是 SQL 语言的替代品。除非您的查询表和结果整齐地映射到类,否则最好编写适当的 SQL 语句。
  • 我是 EF 新手,正在努力学习最佳实践。我认为 EF 的部分好处是无需进行数据库工作并直接处理实体/类?是否按照以下建议对文本 SQL 查询执行最佳实践?

标签: sql linq sql-to-linq-conversion


【解决方案1】:

您可以使用where 代替join

from a in Proposals
join b in Proposal_Minions on a.ID equals b.Proposal_ID
from c in Users
where a.PI_User_ID == c.ID || a.Creator_User_ID == c.ID || b.User_ID == c.ID
select new { a, b, c }

但是,这相当于INNER JOIN。您可以通过

获得外连接效果
from a in Proposals
join b in Proposal_Minions on a.ID equals b.Proposal_ID into j
from pm in j.DefaultIfEmpty()
select new { a, 
             pm,
             c = (from c in Users
                 where a.PI_User_ID == c.ID 
                    || a.Creator_User_ID == c.ID 
                    || pm.User_ID == c.ID
                 select c).FirstOrDefault()
            }

因为你想选择Proposals 只有你可以做

from a in Proposals
join b in Proposal_Minions on a.ID equals b.Proposal_ID into j
from pm in j.DefaultIfEmpty()
where Users.Any(u => a.PI_User_ID == u.ID 
                    || a.Creator_User_ID == u.ID 
                    || pm.User_ID == u.ID)
select a

但这不再是Users 的外连接。另一方面,UsersProposal_Minions 上的外部连接将破坏它们的过滤目的,因为无论如何都会选择所有 Proposals。对于Proposal_Minions 上的外连接仍然如此。

【讨论】:

  • 我认为这里有一个问题,如果 b 没有条目,即使 a.PI_User_ID = c.ID 或 a.Creator_User_ID = c.ID,您也不会得到结果,但是您会在原始 sql 中。
  • @DanKaufman 你是对的!我认为我的编辑将完成 SQL 所做的工作。
  • 当我在 linqpad 中运行第二个 linq 语句时,它给了我一个错误,提示 Proposal_Minions 不包含 User_ID 的定义......这是否意味着“来自 j.DefaultIfEmpty() 中的 pm”是没有从 Proposal_Minions 表中获取 User_ID 字段?
  • 感谢您的更新。我现在得到一个不同的错误。无法创建“用户”类型的常量值。此上下文仅支持原始类型或枚举类型。用户表上的选择是否需要以某种方式仅指向 ID 字段?
  • 这是一个可能仅在 linqpad 中发生的异常,在 VS 代码中不会发生。你试过了吗?
【解决方案2】:

如果需要,您可以针对您的数据库上下文执行原始 sql,并将结果映射到强类型(确保查询结果与类型匹配),例如

IEnumerable<YourStronglyTypedTable> myResults = 
dbConext.ExecuteQuery<YourStronglyTypedTable>("Your SELECT query");

【讨论】:

    猜你喜欢
    • 2013-02-15
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多