2015-12-18 1 views
1

У меня есть ниже SQL QueryНевозможно сформировать правильный запрос Linq, используя список «IN»

;with cte as(
select a.* 
from [dbo].[AccountViewModel] a 
where a.COLLECTORID = 724852 
and a.MONTH = 12 
and a.YEAR=2015) 

select * 
from cte c 
where c.DispCode in ('Deceased','DND','WN','WI','NC','NORESPONSE','SKIP','SHIFTED','SFU') 
OR (c.DispCode in('PTP','DIB','WCE','DP') and convert(varchar(11), c.PTPDate) >=convert(varchar(11), getdate())) 
OR (MONTH(c.LastPaymentDate) = 12 and YEAR(c.LastPaymentDate)=2015) 

Мне нужно преобразовать это в эквивалентный запрос Linq (C#).

КТР часть работает отлично с ниже программы (я перекрестная проверка записи)

private List<AccountViewModel> GetAllAcountsForLoggedInAgents() 
     { 
      var allAcountsForLoggedInAgents = new List<AccountViewModel>(); 

      allAcountsForLoggedInAgents = new ViewModelDatabase() 
        .Accounts 
        .Where(a => 
           a.COLLECTORID == 724852 && 
           a.MONTH == DateTime.Now.Month && 
           a.YEAR == DateTime.Now.Year 
         ) 
        .ToList(); 

      return allAcountsForLoggedInAgents; 
     } 

Однако часть вне КТР не работает должным образом (означает неправильные записи)

GetAllAcountsForLoggedInAgents() 
.Where 
(
    a => 
     ("Deceased,DND,WN,WI,NC,NORESPONSE,SKIP,SHIFTED,SFU".Split(',').Any(x => x.Contains(a.DispCode))) 
     || ("PTP,DIB,WCE,DP".Split(',').Any(b => b.Contains(a.DispCode)) && a.PTPDate >= DateTime.Now) 
     || (a.LastPaymentDate.Value.Month == 12 && a.LastPaymentDate.Value.Year == 2015) 
) 

Я считаю, что, возможно, я использую «ЛЮБОЙ» неправильно.

Может ли кто-нибудь помочь?

Благодаря

ответ

5

Это условие не является такой же, как IN п

("Deceased,DND,WN,WI,NC,NORESPONSE,SKIP,SHIFTED,SFU".Split(',').Any(x => x.Contains(a.DispCode))) 

, потому что он ищет a.DispCode в одной из строк. Вы должны использовать равенство вместо:

("Deceased,DND,WN,WI,NC,NORESPONSE,SKIP,SHIFTED,SFU".Split(',').Any(x => x == a.DispCode)) 

Это не идеально, потому что Split операция не является бесплатным, так что вы не хотите, чтобы сделать это как часть вашего запроса. Изготовление массива static:

static readonly string[] DispCodeFilter = new string[] { 
    "Deceased", "DND", "WN", "WI", "NC", "NORESPONSE", "SKIP", "SHIFTED", "SFU" 
}; 
... 
(DispCodeFilter.Any(x => x == a.DispCode)) 
+0

спасибо, сэр, решение сработало ... им нужно сделать еще несколько тестов, а затем принять –

+0

Сэр, всего 1 вещь, чтобы спросить, так что мне нужно сделать для («PTP, DIB, WCE, DP» .Split (','). Любой (b => b.Contains (a.DispCode)) –

+1

@ priyanka.sarkar Да, вам нужно сделать аналогичное для другого условия 'IN' –

1

Ваше неправильное состояние. Его можно исправить добавлением метода расширения. Я использую общий метод, но вы можете сделать его типичным, если вам нужно/нужно только для строк. Я использую params, поэтому вы можете либо предоставить элементы по одному, либо через split.

public static bool In<T>(this T item, params T[] items) { 
     return items.Any(i=> Equals(item, i)); 
} 

GetAllAcountsForLoggedInAgents().Where(a => a.DispCode.In 
    ("Deceased","DND","WN","WI","NC","NORESPONSE","SKIP","SHIFTED","SFU") 
    || (a.DispCode.In("PTP,DIB,WCE,DP".Split(',')) && 
      a.PTPDate >= DateTime.Now) 
    || (a.LastPaymentDate.Value.Month == 12 && a.LastPaymentDate.Value.Year == 2015) 

)

Одно различие между этим и версия SQL, и причина, вы можете не захотеть, чтобы быть общим, является то, что он чувствителен к регистру: «ш» не равно «WI» ,

1

Вот 2 простых правил для преобразования SQL в Linq

SQL    Linq 
============ ========== 
IN (...)  Contains 
EXISTS (...) Any 

, где Contains представляет собой соответствующий Enumerable/Queryable метод (не путать с string.Contains).

В соответствии с этим, ваши критерии Linq должны быть что-то вроде этого

var DispCodes1 = new [] { "Deceased", "DND", "WN", "WI", "NC", "NORESPONSE", "SKIP", "SHIFTED", "SFU" }; 
var DispCodes2 = new [] { "PTP", "DIB", "WCE", "DP" }; 

GetAllAcountsForLoggedInAgents() 
.Where 
(
    a => 
     DispCodes1.Contains(a.DispCode) 
     || (DispCodes2.Contains(a.DispCode)) && a.PTPDate >= DateTime.Now) 
     || (a.LastPaymentDate.Value.Month == 12 && a.LastPaymentDate.Value.Year == 2015) 
) 

dasblinkenlight answer содержит хороший момент, так что вы можете сделать DispCodes1 и DispCodes2 статичны, но это не важно.

Другого дело, упомянуть о том, что, как вы сделали «КТР часть» не эквивалентен запрос SQL, где cte это просто именованный подзапрос и весь запрос выполняется в базе данных, в то время как в вашей РЕАЛИЗАЦИИ cte части выполняется в базе данных, затем материализуется в памяти, а дополнительный запрос выполняется в памяти с использованием Linq To Objects. Чтобы сделать его полностью эквивалентным и разрешить весь запрос выполнить в базе данных, измените тип результата GetAllAcountsForLoggedInAgents на IQueryable<AccountViewModel> и удалите ToList.

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