Достижение предела параметра 2100 (SQL Server) при использовании Contains()
from f in CUSTOMERS
where depts.Contains(f.DEPT_ID)
select f.NAME
depts
- список (IEnumerable<int>
) идентификаторов отдела
Этот запрос работает нормально, пока вы не передадите большой список (скажем, около 3000 идентификаторов). Затем я получаю эту ошибку:
Неправильный поток протокола входящего потока табличных данных (TDS) удаленных процедур (RPC). Слишком много параметров было предоставлено в этом запросе 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()
, исправил ошибку, но сделал запрос медленным. Есть ли другой способ решить эту проблему? Большое спасибо.
Ответы
Ответ 1
Мое решение (Гиды → Список рекомендаций):
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;
Ответ 2
Почему бы не написать запрос в sql и не прикрепить свою сущность?
Было немного, так как я работал в Linq, но здесь идет:
IQuery q = Session.CreateQuery(@"
select *
from customerTable f
where f.DEPT_id in (" + string.Join(",", depts.ToStringArray()) + ")");
q.AttachEntity(CUSTOMER);
Конечно, вам нужно будет защититься от инъекций, но это не должно быть слишком сложно.
Ответ 3
Вы захотите проверить проект 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.
Ответ 4
У меня была схожая проблема, и у меня есть два способа исправить ее.
Чтобы получить значения, не являющиеся в списке, я использовал За исключением метода или левого соединения.
Ответ 5
Вы всегда можете разбить свой список отделов на более мелкие наборы, прежде чем передавать их в качестве параметров в оператор IN, созданный Linq. См. Здесь:
Разделите большой IEnumerable на меньший IEnumerable на количество исправлений элемента