Достижение ограничения 2100 параметров (SQL Server) при использовании Contains () - PullRequest
57 голосов
/ 18 марта 2009
from f in CUSTOMERS
where depts.Contains(f.DEPT_ID)
select f.NAME

depts - список (IEnumerable<int>) идентификаторов отделов

Этот запрос работает нормально, пока вы не передадите большой список (скажем, около 3000 идентификаторов отделов) .. тогда я получаю эту ошибку:

Неверный поток протокола RPC для входящего потока табличных данных (TDS). Слишком много параметров было предоставлено в этом запросе RPC. Максимум 2100.

Я изменил свой запрос на:

var dept_ids = string.Join(" ", depts.ToStringArray());
from f in CUSTOMERS
where dept_ids.IndexOf(Convert.ToString(f.DEPT_id)) != -1
select f.NAME

использование IndexOf() исправило ошибку, но сделало запрос медленным. Есть ли другой способ решить эту проблему? Большое спасибо.

Ответы [ 5 ]

12 голосов
/ 11 февраля 2014

Мое решение (Руководства -> Список Guid):

List<tstTest> tsts = new List<tstTest>();
for(int i = 0; i < Math.Ceiling((double)Guides.Count / 2000); i++)
{
    tsts.AddRange(dc.tstTests.Where(x => Guides.Skip(i * 2000).Take(2000).Contains(x.tstGuid)));
}
this.DataContext = tsts;
7 голосов
/ 18 марта 2009

Почему бы не написать запрос в sql и не присоединить вашу сущность?

Прошло некоторое время с тех пор, как я работал в Linq, но вот так:

IQuery q = Session.CreateQuery(@"
         select * 
         from customerTable f
         where f.DEPT_id in (" + string.Join(",", depts.ToStringArray()) + ")");
q.AttachEntity(CUSTOMER);

Конечно, вам нужно будет защитить себя от инъекций, но это не должно быть слишком сложно.

1 голос
/ 04 августа 2009

Вы захотите проверить проект LINQKit , так как внутри где-то есть методика объединения таких операторов для решения этой проблемы. Я считаю, что идея состоит в том, чтобы использовать PredicateBuilder, чтобы разбить локальную коллекцию на более мелкие фрагменты, но я не рассмотрел решение подробно, потому что вместо этого я искал более естественный способ справиться с этим.

К сожалению, из ответа Microsoft на мое предложение следует исправить это поведение, что нет планов по решению этой проблемы для .NET Framework 4.0 или даже последующих пакетов обновления.

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=475984

UPDATE:

Я начал обсуждение того, будет ли это исправлено для LINQ to SQL или ADO.NET Entity Framework на форумах MSDN. Пожалуйста, просмотрите эти посты для получения дополнительной информации по этим темам и временного обходного пути, который я придумал, используя XML и SQL UDF.

0 голосов
/ 23 мая 2015

Вы всегда можете разбить свой список узлов на меньшие множества, прежде чем передавать их в качестве параметров в оператор IN, сгенерированный Linq. Смотрите здесь:

Разделите большой IEnumerable на меньший IEnumerable из фиксированного количества элемента

0 голосов
/ 12 ноября 2012

У меня была похожая проблема, и у меня есть два способа ее исправить.

  1. Пересечение метод
  2. присоединиться к идентификаторам

Чтобы получить значения, которых нет в списке, я использовал За исключением метода ИЛИ левого соединения.

Обновление

EntityFramework 6.2 успешно выполняет следующий запрос:

var employeeIDs = Enumerable.Range(3, 5000);
var orders =
    from order in Orders
    where employeeIDs.Contains((int)order.EmployeeID)
    select order;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...