Можете ли вы получить потоковую передачу данных, похожую на DataReader, используя Linq-to-SQL? - PullRequest
4 голосов
/ 21 октября 2010

Я уже давно использую Linq-to-SQL, и он прекрасно работает.Однако в последнее время я экспериментировал с его использованием для получения действительно больших объемов данных и сталкиваюсь с некоторыми проблемами.(Конечно, я понимаю, что L2S не может быть подходящим инструментом для этого конкретного вида обработки, но именно поэтому я экспериментирую - чтобы найти его пределы.)

Вот пример кода:

var buf = new StringBuilder();
var dc = new DataContext(AppSettings.ConnectionString);
var records = from a in dc.GetTable<MyReallyBigTable>() where a.State == "OH" select a;
var i = 0;
foreach (var record in records) {
   buf.AppendLine(record.ID.ToString());
   i += 1;
   if (i > 3) {
      break; // Takes forever...
   }
}

Как только я начинаю перебирать данные, запрос выполняется как ожидалось.Проходя по коду, я сразу же вхожу в цикл, на который я и рассчитывал - это означает, что L2S, похоже, использует DataReader за кулисами вместо того, чтобы сначала извлекать все данные.Однако, как только я попадаю на break, запрос продолжает выполняться и извлекает все остальные записи.Вот мои вопросы к SO-сообществу:

1.) Есть ли способ помешать Linq-to-SQL завершить выполнение действительно большого запроса в середине, как вы можете с помощью DataReader?

2.) Если вы выполняете большой запрос Linq-to-SQL, существует ли способ предотвратить заполнение DataContext информацией отслеживания изменений для каждого возвращаемого объекта.По сути, вместо того, чтобы заполнять память, могу ли я выполнить большой запрос с короткими жизненными циклами объекта, как вы можете с помощью DataReader методов?

Я в порядке, если это не встроенная функциональность DataContext и требует расширения функциональности с некоторыми настройками.Я просто хочу использовать простоту и мощь Linq для больших запросов для ночных задач обработки вместо того, чтобы полагаться на T-SQL для всего.

1 Ответ

7 голосов
/ 24 октября 2010

1.) Есть ли способ остановить Linq-to-SQL от завершения выполнения действительно большой запрос в середине, как вы можно с DataReader?

Не совсем. Как только запрос наконец выполнен, базовый оператор SQL возвращает набор результатов соответствующих записей. Запрос откладывается до этой точки, но не во время обхода.

Для вашего примера вы могли бы просто использовать records.Take(3), но я понимаю, что ваша реальная логика для остановки процесса может быть внешней по отношению к SQL или не легко переводимой.

Вы можете использовать комбинированный подход, построив строго типизированный запрос LINQ, а затем выполнив его со старомодным ADO.NET. Недостатком является то, что вы теряете отображение на класс и вынуждены вручную работать с результатами SqlDataReader. Пример этого показан ниже:

var query = from c in Customers
            where c.ID < 15
            select c;

using (var command = dc.GetCommand(query))
{
    command.Connection.Open();
    using (var reader = command.ExecuteReader())
    {
        int i = 0;
        while (reader.Read())
        {
            Customer c = new Customer();
            c.ID = reader.GetInt32(reader.GetOrdinal("ID"));
            c.Name = reader.GetString(reader.GetOrdinal("Name"));
            Console.WriteLine("{0}: {1}", c.ID, c.Name);
            i++;
            if (i > 3)
                break;
        }
    }
}

2.) Если вы выполняете большой запрос Linq-to-SQL, есть ли способ предотвратить DataContext от заполнения изменить информацию отслеживания для каждого объект возвращен.

Если ваше намерение для определенного запроса состоит в том, чтобы использовать его только для чтения, вы можете отключить отслеживание объектов для повышения производительности, установив для свойства DataContext.ObjectTrackingEnabled значение false:

using (var dc = new MyDataContext())
{
    dc.ObjectTrackingEnabled = false;
    // do stuff
}

Вы также можете прочитать эту тему MSDN: Как: получать информацию только для чтения (LINQ to SQL) .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...