【问题标题】:Multiple join with Lambda Expression使用 Lambda 表达式进行多重连接
【发布时间】:2015-11-24 08:23:19
【问题描述】:

我有三张桌子。

*Contract*
ContractID(PK)
AgentID(FK)
CustomerID(FK)
Status

*Agent*
AgentID
Name

*Customer*
CustomerID
Name

我需要编写一个查询来选择代理名称包含“abc”且客户名称包含“xyz”的所有合同。

我的 Linq 查询是:

from c in ctx.Contracts
from a in ctx.Agents
from cu in ctx.Customers
where c.CustomerID == cu.CustomerID && c.AgentID == a.AgentID && 
a.Name.Contains("abc") && cu.Name.Contains("xyz")
select c

生成的SQL是:

SELECT 
[Filter1].[ContractID] AS [ContractID], 
[Filter1].[AgentID1] AS [AgentID], 
[Filter1].[Status] AS [Status], 
[Filter1].[CustomerID] AS [CustomerID] 
FROM   (SELECT 
        [Extent1].[ContractID] AS [ContractID], 
        [Extent1].[AgentID] AS [AgentID1], 
        [Extent1].[Status] AS [Status], 
        [Extent1].[CustomerID] AS [CustomerID] 
        FROM  [dbo].[Contract] AS [Extent1]
        INNER JOIN [dbo].[Agent] AS [Extent2] ON [Extent1].[AgentID] = 
        [Extent2].[AgentID]
        WHERE [Extent2].[FirstName] LIKE N'%abc%' ) AS [Filter1]
        INNER JOIN [dbo].[Customer] AS [Extent3] ON [Filter1].[CustomerID] =
        [Extent3].[CustomerID]
        WHERE [Extent3].[FirstName] LIKE N'%xyz%'

我正在努力用 Lambda 表达式编写它。任何帮助将不胜感激。

以及如何使用“OR”编写相同的查询。

from c in ctx.Contracts
from a in ctx.Agents
from cu in ctx.Customers
where c.CustomerID == cu.CustomerID && c.AgentID == a.AgentID && 
a.Name.Contains("abc") || cu.Name.Contains("xyz")
select c

【问题讨论】:

    标签: sql linq lambda inner-join


    【解决方案1】:

    AND 查询版本的等效 lambda 表达式应如下所示..

    var result = ctx.Contracts.Join(ctx.Agents.Where(x => x.Name.Contains("abc")), 
                                    c => c.AgentID, 
                                    a => a.AgentID, 
                                    (c, a) => c)                  
                                .Join(ctx.Customers.Where(x => x.Name.Contains("xyz")),
                                      c => c.CustomerID, 
                                     cu => cu.CustomerID, 
                                   (c, cu) => c).ToList();
    

    这是你的OR 版本

    var orResult = ctx.Contracts.Join(ctx.Agents,
                c => c.AgentID,
                a => a.AgentID,
                (c, a) => new {dContract = c, agetnName = a.Name})
                .Join(ctx.Customers,
                    c => c.dContract.CustomerID,
                    cu => cu.CustomerID,
                    (c, cu) => new {ducontract = c, customerName = cu.Name})
            .Where(x => x.ducontract.agetnName.Contains("abc") || x.customerName.Contains("xyz"))
            .Select(y => y.ducontract.dContract).ToList();
    

    【讨论】:

    • 非常感谢。我得到了想要的输出。但是 SQL 略有不同。两种 SQL 在所有情况下都会产生相同的结果吗?选择 [Extent1].[ContractID] 作为 [ContractID]、[Extent1].[AgentID] 作为 [AgentID]、[Extent1].[Status] 作为 [Status]、[Extent1].[CustomerID] 作为 [CustomerID] 从 [ dbo].[Contract] AS [Extent1] INNER JOIN [dbo].[Agent] AS [Extent2] ON [Extent1].[AgentID] = [Extent2].[AgentID] INNER JOIN [dbo].[Customer] AS [ Extent3] ON [Extent1].[CustomerID] = [Extent3].[CustomerID] WHERE ([Extent2].[Name] LIKE N'%abc%') AND ([Extent3].[Name] LIKE N'%xyz% ')。
    • 使用“OR”时,如果合同行中的 AgentID 或 CustomerID 为空,那么返回这些行的最佳方法是什么。
    • 是的,他们有。您在上述评论中发布的 SQL 更有效。在您在问题中发布的查询中,结果集是连接的,而不是直接连接表。
    【解决方案2】:

    使用连接:

    from c in ctx.Contracts
    join a in ctx.Agents on c.AgentID equals a.AgentID
    join cu in ctx.Customers on c.CustomerID equals cu.CustomerID
    where a.Name.Contains("abc") && cu.Name.Contains("xyz")
    select c;
    

    回复:

    以及如何使用“OR”编写相同的查询。

    from c in ctx.Contracts from a in ctx.Agents from cu in ctx.Customers 其中 c.CustomerID == cu.CustomerID && c.AgentID == a.AgentID && a.Name.Contains("abc") || cu.Name.Contains("xyz") 选择 c

    由于 && 操作符比 || 更粘,所以上面的内容不起作用。要正确编写 OR 表达式,请使用:

    from c in ctx.Contracts
    from a in ctx.Agents
    from cu in ctx.Customers
    where 
        c.CustomerID == cu.CustomerID && c.AgentID == a.AgentID
        && ( a.Name.Contains("abc") || cu.Name.Contains("xyz") ) 
    select c
    

    你原来的查询条件,没有括号的那个..

    where c.CustomerID == cu.CustomerID && c.AgentID == a.AgentID && 
       a.Name.Contains("abc") || cu.Name.Contains("xyz") 
    

    ..被评估如下。 && 比 || 更粘人

    where 
        (
            c.CustomerID == cu.CustomerID 
            && c.AgentID == a.AgentID 
            && a.Name.Contains("abc")
        ) 
        || cu.Name.Contains("xyz") 
    

    最后,这就是你想要的:

    from c in ctx.Contracts
    join a in ctx.Agents on c.AgentID equals a.AgentID
    join cu in ctx.Customers on c.CustomerID equals cu.CustomerID
    where a.Name.Contains("abc") || cu.Name.Contains("xyz")
    select c;
    

    顺便说一句,如果可以使用 Linq,为什么还要使用 lambda?或者你可以混合使用 Linq 和 lambda。仅使用 lambda 会使查询难以阅读:http://www.ienablemuch.com/2014/03/highfalutin-code-1.html

    【讨论】:

    • 谢谢。我也熟悉Linq。但是我使用表达式树来动态构建 Where 子句,我发现使用动态 where 子句的唯一方法是编写 Lambda 表达式。
    猜你喜欢
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-10
    • 1970-01-01
    • 1970-01-01
    • 2012-09-14
    • 1970-01-01
    相关资源
    最近更新 更多