2012-04-20 3 views
2

Это мой старый код:LINQ - ЛЕВЫЙ присоединиться

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(); 

Это то, что я получил до сих пор, но ничего не возвращает. Что я делаю не так?

+2

Может быть, вы можете начать с выбора из одной таблицы, а затем сохранить присоединение новых таблиц по одному за раз, пока вы не найдете проблема. – mbeckish

+0

@mbeckish Я так и делал, но он все еще не работает ... Кажется, что соединение бесполезно ... Любой другой совет? – Willem

+2

@ Виллем - Уххх ... ты действительно понял, что сказал мбеккиш? «Я сделал, но он все еще не работает» - это нечувствительный ответ на этот комментарий. Если да, то в какой момент это происходит? В чем проблема? –

ответ

3

Я заметил, что в ваших инструкциях 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(); 

Update:

// 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();  

Mock с использованием данных: http://ideone.com/XEqf4

+0

Спасибо за ответ Брэд, но он по-прежнему возвращает 0 результатов. Как только я добавляю первое соединение, результат равен 0. На данный момент обе таблицы пусты. 'DestinctList' имеют результаты ... Итак, правильно ли я делал левые соединения или я что-то пропустил? – Willem

+1

@ Виллем, глядя на ваш исходный код, похоже, что вы НЕ хотите возвращать какие-либо данные, если таблицы ClientAlias ​​или ClientProductAlias ​​не соответствуют данным в вашем destinctList. Я [издевался над примером] (http://ideone.com/XEqf4), чтобы играть с данными здесь, чтобы показать, как он возвращает результат. Я также обновил свой ответ, чтобы включить альтернативный метод соединения для отображения данных, не найденных в других списках. –

+0

Кажется, работает и на меня. У меня были большие проблемы с работой левого соединения в Linq из-за перевода (внутреннее соединение с условиями для работы как левое соединение). Получено от нескольких минут до 5 секунд. Большое спасибо! – Rufix

Смежные вопросы