Linq to SQL, как это сделать ", где [столбец] в (список значений)"
У меня есть функция, где я получаю список идентификаторов, и мне нужно вернуть список, соответствующий описанию, связанному с идентификатором. Например:.
public class CodeData
{
string CodeId {get; set;}
string Description {get; set;}
}
public List<CodeData> GetCodeDescriptionList(List<string> codeIDs)
//Given the list of institution codes, return a list of CodeData
//having the given CodeIds
}
Итак, если бы я сам создавал sql для этого, я бы просто сделал что-то вроде следующего (где предложение in содержит все значения в аргументе codeIds):
Select CodeId, Description FROM CodeTable WHERE CodeId IN ('1a','2b','3')
В Linq to Sql я не могу найти эквивалент предложения "IN". Самое лучшее, что я нашел до сих пор (что не работает):
var foo = from codeData in channel.AsQueryable<CodeData>()
where codeData.CodeId == "1" || codeData.CodeId == "2"
select codeData;
Проблема заключается в том, что я не могу динамически генерировать список "OR" для linq для sql, потому что они установлены во время компиляции.
Как выполнить условие where, которое проверяет столбец, находится в динамическом списке значений с использованием Linq to Sql?
Ответы
Ответ 1
Использование
where list.Contains(item.Property)
Или в вашем случае:
var foo = from codeData in channel.AsQueryable<CodeData>()
where codeIDs.Contains(codeData.CodeId)
select codeData;
Но вы также можете сделать это в виде точечной нотации:
var foo = channel.AsQueryable<CodeData>()
.Where(codeData => codeIDs.Contains(codeData.CodeId));
Ответ 2
Вы также можете использовать:
List<int> codes = new List<int>();
codes.add(1);
codes.add(2);
var foo = from codeData in channel.AsQueryable<CodeData>()
where codes.Any(code => codeData.CodeID.Equals(code))
select codeData;
Ответ 3
Я использовал метод в ответе Джона Скита, но мне пришло другое, используя Concat
. Метод Concat
выполнялся немного лучше в ограниченном тесте, но это хлопот, и я, вероятно, просто придерживаюсь Contains
, или, может быть, я напишу вспомогательный метод, чтобы сделать это для меня. В любом случае, здесь другой вариант, если кому-то интересно:
Метод
// Given an array of id's
var ids = new Guid[] { ... };
// and a DataContext
var dc = new MyDataContext();
// start the queryable
var query = (
from thing in dc.Things
where thing.Id == ids[ 0 ]
select thing
);
// then, for each other id
for( var i = 1; i < ids.Count(); i++ ) {
// select that thing and concat to queryable
query.Concat(
from thing in dc.Things
where thing.Id == ids[ i ]
select thing
);
}
Тест производительности
Это не было отдаленно научным. Я предполагаю, что ваша структура базы данных и количество идентификаторов, включенных в список, окажут значительное влияние.
Я установил тест, где я провел 100 испытаний каждый из Concat
и Contains
, где каждое исследование включало выбор 25 строк, заданных рандомизированным списком первичных ключей. Я запускаю это примерно десяток раз, и чаще всего метод Concat
выходит на 5 - 10% быстрее, хотя один раз метод Contains
выиграл всего лишь smidgen.
Ответ 4
var filterTransNos = (from so in db.SalesOrderDetails
where ItemDescription.Contains(ItemDescription)
select new { so.TransNo }).AsEnumerable();
listreceipt = listreceipt.Where(p => filterTransNos.Any(p2 => p2.TransNo == p.TransNo)).ToList();