Как я могу использовать Nhibernate для получения данных, когда «WHERE IN () ”Тысячи значений? (слишком много параметров в sql)

Проблема : Nhibernate анализирует каждое значение в sql «WHERE IN ()» как параметры, а сервер MS SQL не поддерживает достаточное количество параметров (более 2000 ).

Я использую Nhibernate с Linq для получения данных с SQL-сервера, и мне нужно загрузить множество сущностей на основе уже известных идентификаторов.

Мой код выглядит примерно так:

int[] knownIds = GetIDsFromFile();
var loadedEntities = _Repository.GetAll()
                                .Where(x => knownIds.Contains(x.ID))
                                .ToList();

Что дает sql вроде этого:

SELECT id, name FROM MyTable 
WHERE id IN (1 /* @p0 */,2 /* @p1 */,3 /* @p2 */,4 /* @p3 */, 5 /* @p4 */)

Если в knownIds слишком много значений, то этот код выдаст исключение из-за множества параметров, которые использует NHibernate.

Я думаю, что лучшим решением было бы, если бы я мог заставьте NHibernate использовать только 1 параметр для всего "WHERE IN ()", но я не знаю, как это сделать:

SELECT id, name FROM MyTable WHERE id IN (1, 2, 3, 4, 5 /* @p0 */)

Я буду рад услышать любые идеи, как решить эту проблему - либо путем расширения LINQ провайдера или другими способами. Одно из решений - просто выполнить запрос x раз (knownIds.Count / 1000), но я предпочитаю универсальное решение, которое будет работать для всех моих сущностей.

Я попытался расширить возможности поставщика LINQ, выполнив поиск в Google и Stackoverflow. , однако я не могу найти решение, и у меня нет опыта работы ни с HQL, ни с построителем деревьев. Вот несколько сайтов, на которых я был:

ОБНОВЛЕНИЕ: Я знаю, что использование такого количества значений в предложении IN - не лучшая практика, но я не знаю лучшего решения для того, что я хочу сделать.
Рассмотрим компанию, в которой все клиенты платят за услуги компании один раз в месяц. Сама компания не занимается платежами, но есть другая компания, которая собирает деньги. Один раз в месяц компания получает файл, содержащий статус этих платежей: были ли они оплачены или нет. Файл содержит только идентификатор конкретного платежа, но не идентификатор клиента. Компания с 3000 клиентов в месяц будет производить 3000 платежей LogPayments каждый месяц, статус которых необходимо обновить. Через год будет около 36 000 LogPayments, поэтому простая загрузка их всех тоже не кажется хорошим решением.

МОЕ РЕШЕНИЕ: Спасибо за все полезные ответы. В конце концов, я решил использовать комбинацию ответов. Для этого конкретного случая я сделал что-то вроде предложенного Четвертого, так как это значительно повысит производительность. Однако я также реализовал общий метод, предложенный Стефаном Штайнеггером, потому что мне нравится, что я могу это сделать, если это то, что я действительно хочу. Кроме того, я не хочу, чтобы моя программа вылетала из-за исключения, поэтому в будущем я все равно буду использовать этот метод ContainsAlot в качестве защиты.

20
задан Community 23 May 2017 в 10:29
поделиться