LINQ2SQL выбирает строки на основе больших где - PullRequest
0 голосов
/ 30 мая 2011

Я ищу группу int32 в базе данных SQL (Compact edition) с использованием LINQ2SQL.

Моя главная проблема заключается в том, что у меня есть большой список (тысячи) int32, и я хочу, чтобы все записи находились вБД, где поле id в БД соответствует любому из моих int32.В настоящее время я выбираю одну строку за раз, эффективно просматривая индекс тысячи раз.

Как я могу оптимизировать это?Временная таблица?

Ответы [ 5 ]

1 голос
/ 30 мая 2011

Для поиска по тысячам значений вы можете выбрать:

  • Отправка блока XML хранимой процедуре (сложно, но выполнимо)
  • Создание временной таблицы, массовая загрузка данных, затем присоединение к ней (может вызвать проблемы с параллелизмом)
  • Выполнение нескольких запросов (т.е. разбить вашу группу идентификаторов на куски по тысяче или около того и использовать решение BrokenGlass)

Я не уверен, что вы можете сделать с Compact Edition.

1 голос
/ 30 мая 2011

Похоже, вы могли бы использовать запрос Contains:

int[] intArray = ...;
var matches = from item in context.SomeTable 
              where intArray.Contains(item.id) 
              select item;
0 голосов
/ 31 мая 2011

Я пришел к этому решению linq после того, как устал от написания кода ручной пакетной обработки.Это не идеально (то есть партии не совсем идеально), но это решает проблему.Очень полезно, когда вам не разрешено писать хранимые процедуры или функции SQL.Работает практически с каждым выражением linq.

Наслаждайтесь:

    public static IQueryable<TResultElement> RunQueryWithBatching<TBatchElement, TResultElement>(this IList<TBatchElement> listToBatch, int batchSize, Func<List<TBatchElement>, IQueryable<TResultElement>> initialQuery)
    {
        return RunQueryWithBatching(listToBatch, initialQuery, batchSize);
    }

    public static IQueryable<TResultElement> RunQueryWithBatching<TBatchElement, TResultElement>(this IList<TBatchElement> listToBatch, Func<List<TBatchElement>, IQueryable<TResultElement>> initialQuery)
    {
        return RunQueryWithBatching(listToBatch, initialQuery, 0);
    }

    public static IQueryable<TResultElement> RunQueryWithBatching<TBatchElement, TResultElement>(this IList<TBatchElement> listToBatch, Func<List<TBatchElement>, IQueryable<TResultElement>> initialQuery, int batchSize)
    {
        if (listToBatch == null)
            throw new ArgumentNullException("listToBatch");

        if (initialQuery == null)
            throw new ArgumentNullException("initialQuery");

        if (batchSize <= 0)
            batchSize = 1000;

        int batchCount = (listToBatch.Count / batchSize) + 1;

        var batchGroup = listToBatch.AsQueryable().Select((elem, index) => new { GroupKey = index % batchCount, BatchElement = elem }); // Enumerable.Range(0, listToBatch.Count).Zip(listToBatch, (first, second) => new { GroupKey = first, BatchElement = second });

        var keysBatchGroup = from obj in batchGroup
                                     group obj by obj.GroupKey into grouped
                                     select grouped;

        var groupedBatches = keysBatchGroup.Select(key => key.Select((group) => group.BatchElement));

        var map = from employeekeysBatchGroup in groupedBatches
                  let batchResult = initialQuery(employeekeysBatchGroup.ToList()).ToList() // force to memory because of stupid translation error in linq2sql
                  from br in batchResult
                  select br;

        return map;
    }

Использование:

using (var context = new SourceDataContext())
{
    // some code
    var myBatchResult = intArray.RunQueryWithBatching(batch => from v1 in context.Table where batch.Contains(v1.IntProperty) select v1, 2000);
    // some other code that makes use of myBatchResult
}

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

0 голосов
/ 30 мая 2011

Я бы предпочел написать хранимую процедуру для поиска. Если у вас есть индекс в поле, которое вы ищете, это сделает вашу жизнь намного проще в будущем, когда количество строк для обработки увеличится.

Сложность, с которой вы столкнетесь, - это написание оператора select, который может выполнить предложение IN из входного параметра. Вам нужно иметь функцию Table-Valued для преобразования строки (идентификаторов) в столбец и использовать этот столбец в предложении IN. как:

Select *
From SomeTable So
Where So.ID In (Select Column1 From dbo.StringToTable(InputIds))
0 голосов
/ 30 мая 2011

Вставьте свои целые числа в таблицу SQL, затем выполните:

var items = from row in table
            join intRow in intTable on row.TheIntColumn equals intRow.IntColumn
            select row;

Изменить 1 и 2: Изменен ответ, поэтому он объединяет 2 таблицы, а не коллекции.

...