2009-05-10 2 views
26

Я экспериментирую с LINQ с некоторого времени. Типичный метод для перечисления коллекции и изменить некоторые его свойства в моем коде будет выглядеть так:Максимальное количество параметров в sql-запросе

ATDataContext dc = new ATDataContext(Settings.connection_string); 

int[] col = ListViewClass.getListViewSelectedPositionTags(listView); 

try 
{ 
    foreach (var item in col) 
    { 
     var ctx = (from r in dc.MailingLists 
        where r.ID == item 
        select r).Single(); 

     ctx.Excluded = 'Y'; 
     ctx.ExcludedComments = reason; 
    } 

    dc.SubmitChanges(); 
} 

Некоторое время получили совет, чтобы сделать это, ... кажется, гораздо более разумным способом:

var ctx = from r in dc.MailingLists 
    where col.Contains(r.ID) 
    select r; 

foreach (var item in ctx) 
{ 
    item.Excluded = 'Y'; 
    item.ExcludedComments = reason; 
} 

dc.SubmitChanges(); 

Iit имеет смысл на стольких уровнях, и я люблю это решение. Это умный и быстрый, чем первый.

Я использовал это решение в производственной среде в течение некоторого времени.

Каково было мое удивление после того, как несколько недель, когда поиску в лог-файлы приложений и убедиться в этом:

«Поступающий поток данных в табличной форме (TDS) удаленный вызов процедур (RPC) поток протокола неверен Слишком много параметров. были предоставлены в этом запросе RCP. Максимум 2100. "

LINQ к SQL преобразует where col.Contains(r.ID) в IN положение ищет что-то вроде:
WHERE ID IN (@ p1, @ p1, @ p2 ...)

col коллекция достигла (в моем случае) более 2100 элементов и запрос не удалось выполнить. Я провел некоторое исследование проблемы, и я закончил:

«... Максимальное количество параметров в sql-запросе - 2100. Существует больше ограничений, таких как тот факт, что вся строка запроса не может быть больше чем 8044 символа. "

Я так много любил второе решение. Я так разочарован этими жестко закодированными ограничениями SQL Server.

Я что-то пропустил? Есть ли что-нибудь, что я могу сделать, чтобы использовать версию «where col.Contains (r.ID)»?

С уважением Мариуш

пс. (Я использую Win XP, C# с LINQ и SQL 2005 Express).

+0

Извинения. Мне не удалось форматировать образцы кода. Если бы кто-то мог помочь, я был бы очень признателен ... – Mariusz

+0

отформатирован; вы можете использовать кнопки «code» и «quote», чтобы сделать это в редакторе. –

+0

большое спасибо. просто копаясь в вашем другом ответе. кажется, что это будет не просто кусок пирога :-) – Mariusz

ответ

39

Пределы are hard-coded:

  • Параметры в хранимой процедуре 2,100
  • Параметры в определенной пользователем функции 2,100

я написал некоторый код до этого разделить Contains запроса в партиях и объединил результаты ... see here for more.

+5

получается, что сообщение об ошибке/документация неверна.Они должны иметь чек, который идет '> = 2100', а не> 2100, потому что фактический предел составляет 2099, только что наблюдал это, пытаясь отправить 4 партии параметров, что дает ровный размер 525 –

+1

@JonnyLeeds интересный; Интересно, делает ли он что-то вроде всегда, включая пространство для возвращаемого значения (даже если оно не используется), которое реализовано как параметр –

+0

да, возможно. В документации там конкретно упоминаются функции и хранимые процедуры, тогда как я просто запускал большой набор вставок, однако исключения из запуска 'command.Execute [Blah]' (в C#) также упоминают 2100 –

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