【问题标题】:LINQ - LEFT joinLINQ - 左连接
【发布时间】:2012-04-20 13:22:34
【问题描述】:

这是我的旧代码:

var destinctList = HoldingsList.DistinctBy(x => new { x.ClientName, x.ProductName }).Select(x => new { ClientName = x.ClientName, ClientProductName = x.ProductName }).ToList();

foreach (var item in destinctList)
{

    var clientAlias = (from ca in someContext.ClientAlias
                       where ca.Name == item.ClientName
                       orderby ca.CreationDate descending
                       select ca).FirstOrDefault();

    if (clientAlias != null)
    {
        destinctList.Where(x => x.ClientName == item.ClientName).ForEach(x => x.ClientID = clientAlias.ClientID);
    }

    ClientProductAlias clientProductAlias = null;

    if (clientAlias != null)
    {
        clientProductAlias = (from ca in someContext.ClientProductAlias
                              where ca.Name == item.ClientProductName
                              && ca.ClientID == clientAlias.ClientID
                              orderby ca.CreationDate descending
                              select ca).FirstOrDefault();
    }

    if (clientProductAlias != null)
    {
        destinctList.Where(x => x.ClientProductName == item.ClientProductName).ForEach(x => x.ClientProductID = clientProductAlias.ClientProductID);
    }
}

这很好用,但花了很长时间。

现在我想让这一切都与连接一起工作。这是我到目前为止所拥有的:

(from list in destinctList
join ca in someContext.ClientAlias on list.ClientName equals ca.Name into list_client_join
from list_client in list_client_join.DefaultIfEmpty
join cpa in someContext.ClientProductAlias on new { ClientID = (long)list.ClientID, Name = list.ClientProductName } equals new { cpa.ClientID, cpa.Name } into j1
from j2 in j1.DefaultIfEmpty
orderby list_client.CreationDate descending
orderby j2.CreationDate descending
select new { ClientID = list_client.ClientID, 
             ClientName = list.ClientName, 
             ClientProductID = j2.ClientProductID, 
             ClientProductName = list.ClientProductName }).ToList();

这是我到目前为止得到的,但没有返回任何东西。我做错了什么?

【问题讨论】:

  • 也许您可以先从一张表中进行选择,然后不断加入新表,直到找到问题为止。
  • @mbeckish 我做了,但它仍然无法正常工作......连接似乎搞砸了查询......还有其他建议吗?
  • @Willem - 呃……你真的明白 mbeckish 说的是什么吗? “我做到了,但它仍然无法正常工作”是对该评论的无意义的回应。如果你这样做了,它会在什么时候失败?加入有什么问题?
  • @MystereMan 我添加第一个联接后,结果为 0。此时两个表都是空的。 DestinctList 有结果...那么,我的左连接是正确的还是我遗漏了什么?

标签: c# .net linq join


【解决方案1】:

我注意到您的 DefaultIfEmpty 语句缺少括号,而且我认为问题在于它如何处理与空数据的连接。我认为您肯定需要where j1.Any() 电话,您可能还需要where list_client_join.Any()

(from list in destinctList 
join ca in someContext.ClientAlias on list.ClientName equals ca.Name into list_client_join 
//where list_client_join.Any ()
from list_client in list_client_join.DefaultIfEmpty() 
join cpa in someContext.ClientProductAlias on new { ClientID = (long)list.ClientID, Name = list.ClientProductName } equals 
   new { cpa.ClientID, cpa.Name } into j1 
// maybe needs the following:
where j1.Any ()
from j2 in j1.DefaultIfEmpty() 
orderby list_client.CreationDate descending 
orderby j2.CreationDate descending 
select new { ClientID = list_client.ClientID,  
             ClientName = list.ClientName,  
             ClientProductID = j2.ClientProductID,  
             ClientProductName = list.ClientProductName }).ToList(); 

更新:

// alternate query
(from list in destinctList  
let ca = someContext.ClientAlias
            .OrderByDescending (cca => cca.CreationDate)
            .FirstOrDefault (cca => cca.Name == list.ClientName)
let cca = someContext.ClientProductAlias
            .OrderByDescending (ccpa => ccpa.CreationDate)
            .FirstOrDefault(ccpa => int.Equals(ccpa.ClientID,
                           ca == null ? -1 : ca.ClientID) && 
                          string.Equals(ccpa.Name,list.ClientProductName))
select new
{
    ClientID = ca != null ? ca.ClientID : -1,
    ClientName = list.ClientName,
    ClientProductID = cca != null ? cca.ClientProductID : -1,
    ClientProductName = list.ClientProductName 
}
).ToList();     

使用数据模拟:http://ideone.com/XEqf4

【讨论】:

  • 感谢 Brad 的回答,但仍然返回 0 个结果。一旦我添加了第一个连接,结果就是 0。此时两个表都是空的。 DestinctList 有结果...那么,我的左连接是正确的还是我遗漏了什么?
  • @Willem,查看您的原始代码,如果 ClientAlias 或 ClientProductAlias 表与您的 destinctList 中的数据不匹配,您似乎不想返回任何数据。我已经mocked up an example 在这里使用数据来显示它如何返回结果。我还更新了我的答案,加入了一种替代连接方法来显示在其他列表中找不到的数据。
  • 似乎也适合我。由于翻译,我在 Linq 中的左连接性能存在很大问题(内连接有条件作为左连接工作)。从几分钟到5秒。非常感谢!
猜你喜欢
  • 2017-04-10
  • 2011-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多