2016-06-09 3 views
1

При запросе, который возвращает несколько результатов, мы повторяем между ними, используя NextResult()SqlDataReader. Таким образом, мы последовательно получаем результаты.SqlDataReader получить конкретный ResultSet

Есть ли способ получить результат случайным/не последовательным способом. Например, прыгайте сначала к третьему результату, затем к первому e.t.c

Я ищу, есть ли что-то вроде rdr.GetResult(1) или обходной путь.

Так как я спросил Почему я хочу что-то вроде этого,

  • Прежде всего у меня нет доступа к запросу и поэтому я не могу изменения, так что в моем клиенте я будет иметь результаты в последовательность, которую сервер пишет/производит.
  • Для обработки (создания коллекций, сущностей -> бизнес-логики) первой мне нужна информация как второй, так и третьей.
  • Опять же, поскольку это не вариант изменения кода, я не могу каким-либо образом (без написания большого количества кода) «хранить» информацию о соединении (например, идентификаторы), чтобы подключиться на более позднем этапе двумя ResultSets
  • Самое «элегантное» решение (конечно, не единственное) состоит в том, чтобы обрабатывать результирующие наборы некорректно. Поэтому я спрашиваю, есть ли такой способ.

Update 13/6

Хотя Jeroen Mostert answer дает вдумчивое объяснение на почему, Think2ceCode1ce answer показывает правильные направления обхода. Содержание link в комментариях, как в дополнительных dataset может быть использовано для работы в async способом. ИМХО, это был бы путь, если бы собирался написать общее решение. Однако в моем случае я основывал свое решение на характере моих данных и на их логике. Короче говоря, (1) я читаю данные по мере их последовательного использования, используя SqlDataReader; (2) Я храню некоторые данные, которые мне нужны в словаре и коллекции, когда я читаю первый в строке, но второй в логическом ResultSet; (3) Когда я читаю третий в строке, но сначала в логическом ResultSet, я повторяюсь через коллекцию, которую я создал ранее, и на основе данных словаря я создаю свой окончательный результат.

Последний код кажется более эффективным и более ремонтопригодным, чем при использовании async DataAdapter. Однако это очень конкретное решение, основанное на моих данных.

+3

'SqlDataReader' является курсором только вперед –

+0

Зачем вы хотите это сделать? Вы пытаетесь избежать выполнения одного из заявлений? –

+1

Я неправильно понял ваш вопрос, поэтому удалил свой ответ. Но в качестве комментария я просто упомянул, что DataTable и DataSet - это объекты, которые вы используете для кэширования локальных копий запросов для произвольного доступа и/или модификации. –

ответ

3

Предоставляет способ чтения прямого потока строк из базы данных SQL .

https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader(v=vs.110).aspx

Вы должны использовать DataAdapter отключенный и не последовательный доступ. Чтобы использовать это, вам просто нужно изменить бит вашего кода ADO.NET.

Вместо

SqlDataReader sqlReader = sqlCmd.ExecuteReader(); 

Вам нужен

DataTable dt = new DataTable(); 
SqlDataAdapter sqlAdapter = new SqlDataAdapter(sqlCmd); 
sqlAdapter.Fill(dt); 

Если SQL возвращает несколько наборов результатов, вы должны использовать DataSet вместо DataTable, а затем получить доступ результирующих наборов, как ds.Tables[index_or_name].

https://msdn.microsoft.com/en-us/library/bh8kx08z(v=vs.110).aspx

+0

'DataSet' кажется правильным путем, однако (после некоторого чтения и тестирования) у меня есть некоторые проблемы с производительностью. Более того, «DataAdapter» не поддерживает (пока) методы «Async», которые являются одной из возможностей, которые я планирую использовать в будущем. – Athafoud

+1

Ожидаете ли вы чего-то подобного? См. Ответ от * Fred * по адресу https://social.msdn.microsoft.com/Forums/en-US/027d4e62-d1c3-4939-a84a-7038994cdfe2/asynchronous-sqldataadapter?forum=adodotnetdataset – niksofteng

+0

Да, я уже смотрю на него и Я планирую проверить это. это действительно очень хороший подход и решает проблему «DataAdapter», Async «недостаток». – Athafoud

2

Нет, это невозможно. Причина довольно элементарная: если пакет возвращает несколько результатов, он должен возвращать их по порядку - оператор, который возвращает результирующий набор # 2, не запускается до того, который возвращает результирующий набор # 1, и клиент не имеет никакого способа говоря: «Пожалуйста, просто пропустите это первое утверждение целиком» (поскольку это может иметь ужасные последствия для партии в целом). В самом деле, вообще нет вообще смысла рассказывать, сколько результатов будет производиться партиями - все это делается во время выполнения, сервер заранее не знает, что произойдет.

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

Есть два возможных глобальных обходные:

  • Если обрабатывать все данные и кэш локально (с DataAdapter, например), вы можете вернуться назад и вперед в данных, как вам угодно, но это требует сохраняя все данные в памяти.
  • Если вы включите MARS (несколько наборов активных результатов), вы можете выполнить другой запрос, даже если первый из них все еще обрабатывается. Это требует разделения существующего единого пакетного кода на отдельные операторы (что, если вы действительно ничего не можете изменить о SQL вообще, не является вариантом), но вы можете пройти через результирующие наборы (без кеширования). Тем не менее, вы не сможете «вернуться» в пределах одного набора результатов.
Смежные вопросы