【问题标题】:How to write join query with multiple column - LINQ如何编写具有多列的连接查询 - LINQ
【发布时间】:2021-01-16 09:48:30
【问题描述】:

我有一个情况,两个表应该用或条件连接多个列。在这里,我有一个 sql 查询示例,但我无法将其转换为 linq 查询。

select cm.* from Customer cm
inner join #temp tmp
on cm.CustomerCode = tmp.NewNLKNo or cm.OldAcNo = tmp.OldNLKNo

这就是我编写 linq 查询的方式

await (from cm in Context.CustomerMaster
                         join li in list.PortalCustomerDetailViewModel
                         on new { OldNLKNo = cm.OldAcNo, NewNLKNo = cm.CustomerCode } equals new { OldNLKNo = li.OldNLKNo, NewNLKNo = li.NewNLKNo }
                         select new CustomerInfoViewModel
                         {
                             CustomerId = cm.Id,
                             CustomerCode = cm.CustomerCode,
                             CustomerFullName = cm.CustomerFullName,
                             OldCustomerCode = cm.OldCustomerCode,
                             IsCorporateCustomer = cm.IsCorporateCustomer
                         }).ToListAsync();

但是这个查询没有按预期返回。如何将此 sql 查询转换为 linq。

谢谢

【问题讨论】:

标签: sql sql-server linq asp.net-core


【解决方案1】:

您没有确定list.PortalCustomerDetailViewModel 是数据库中的信息,还是本地进程中的信息。看来这是在您的本地进程中,您的查询必须将其传输到数据库(也许这就是为什么它在您的 SQL 中是 Tmp 的原因?)

要求:给我所有 CustomerMasters 的所有属性,其中至少存在一个 PortalCustomerDetailViewModel

   customerMaster.CustomerCode == portalCustomerDetailViewModel.NewNLKNo
|| customerMaster.OldAcNo == portalCustomerDetailViewModel.OldNLKNo

您不能使用普通的 Join,因为 Join 与 AND 一起使用,您想与 OR 一起使用

您可以做的是选择所有满足所提供 OR 的 PortalCustomerDetailViewModel 的所有 CustomerMaster:

我只将 list.PortalCustomerDetailViewModel 的那些属性转移到我需要在 OR 表达式中使用的数据库中:

var checkProperties = list.PortalCustomerDetailViewModel
    .Select(portalCustomerDetail => new
    {
        NewNlkNo = portalCustomerDetail.NewNlkNo,
        OldNLKNo = portalCustomerDetail.OldNLKNo,
    });

var result = dbContext.CustomerMasters.Where(customerMaster =>
    checkProperties.Where(checkProperty => 
        customerMaster.CustomerCode == checkProperty.NewNLKNo
     || customerMaster.OldAcNo == checkProperty.OldNLKNo)).Any()))
.Select(customerMaster => new CustomerInfoViewModel
{
    Id = customerMaster.Id,
    Name = customerMaster.Name,
    ...
});

换句话说:从list.PortalCustomerDetailViewModel中的每个portalCustomerDetail中,提取属性NewNKLNo和OldNLKNo。

然后从 CustomerMasters 表中,仅保留那些至少具有一个 portalCustomerDetail 且具有 OR 语句中描述的属性的 customerMasters。

从每个剩余的 CustomerMaster 中,创建一个包含属性的新 CustomerInfoViewModel ...

【讨论】:

    【解决方案2】:
    select cm.* from Customer cm
    inner join #temp tmp
    on cm.CustomerCode = tmp.NewNLKNo or cm.OldAcNo = tmp.OldNLKNo
    

    您不必使用连接语法。在 where 子句中添加谓词可以获得相同的结果。尝试使用以下代码:

    await (from cm in Context.CustomerMaster
           from li in list.PortalCustomerDetailViewModel
           where cm.CustomerCode == li.NewNLKNo || cm.OldAcNo = li.OldNLKNo
           select new CustomerInfoViewModel
                 {
                    CustomerId = cm.Id,
                    CustomerCode = cm.CustomerCode,
                    CustomerFullName = cm.CustomerFullName,
                    OldCustomerCode = cm.OldCustomerCode,
                    IsCorporateCustomer = cm.IsCorporateCustomer
                  }).ToListAsync();
    

    【讨论】:

      【解决方案3】:
      var result=_db.Customer
      .groupjoin(_db.#temp ,jc=>jc.CustomerCode,c=> c.NewNLKNo,(jc,c)=>{jc,c=c.firstordefault()})
      .groupjoin(_db.#temp ,jc2=>jc2.OldAcNo,c2=> c2.OldNLKNo,(jc2,c2)=>{jc2,c2=c2.firstordefault()})
      .select(x=> new{
      //as you want
      }).distinct().tolist();
      

      【讨论】:

        猜你喜欢
        • 2018-09-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多