DataReader или DataSet при извлечении нескольких наборов записей в ASP.NET - PullRequest
11 голосов
/ 08 октября 2008

У меня есть страница ASP.NET, которая имеет набор элементов управления, которые необходимо заполнить (например, раскрывающиеся списки).

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

Я мог бы вернуть несколько таблиц в DataSet, или я мог бы вернуть DataReader и использовать .NextResult, чтобы поместить каждый набор результатов в пользовательский бизнес-класс.

Скорее всего, я увижу достаточно большое преимущество в производительности при использовании подхода DataReader или мне просто нужно использовать подход DataSet?

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

Ответы [ 10 ]

7 голосов
/ 21 июня 2009
  1. Если у вас есть более 1000 записей для извлечения из базы данных.
  2. Если вас не очень интересует пользовательское хранение и пользовательские подкачки " для GridView "
  3. Если у вашего сервера нехватка памяти.
  4. Если нет проблем с подключением к ваша база данных каждый раз, когда эта страница называется.

Тогда я думаю, что лучше использовать DataReader.

еще

  1. Если у вас есть менее 1000 записей для извлечения из базы данных.
  2. Если вы заинтересованы в хранение и пейджинг " для GridView"
  3. Если на вашем сервере нет памяти стресс.
  4. Если вы хотите подключиться к вашему База данных только один раз и получить Преимущества Кэширование .

Тогда я думаю, что лучше использовать DataSet.

Надеюсь, я прав.

4 голосов
/ 19 ноября 2010

Видя, что ни один ответ еще не отмечен, хотя уже есть много хороших ответов, я подумал, что добавлю еще два бита.

Я бы использовал DataReaders, так как они немного быстрее (если вам нужна производительность или вам нужно столько, сколько вы можете получить). Большинство проектов, над которыми я работал, содержат миллионы записей в каждой из таблиц, и производительность вызывает беспокойство.

Некоторые люди говорят, что отправлять DataReader между слоями не очень хорошая идея. Лично я не вижу в этом проблемы, поскольку «DbDataReader» технически не привязан (или не должен быть) к базе данных. То есть вы можете создать экземпляр DbDataReader без необходимости в базе данных.

Почему я это делаю по следующим причинам: Часто (в веб-приложении) вы генерируете либо Html, либо Xml или JSON, либо какое-то другое преобразование ваших данных. Так зачем переходить от DaraReader к какому-либо объекту POCO только для преобразования его обратно в XML или JSON и отправки по сети. Этот тип процесса обычно требует 3 преобразования и загрузку экземпляров объекта только для того, чтобы выбросить их почти мгновенно.

В некоторых ситуациях это нормально или ничего не поделаешь. Мой уровень данных обычно отображает два метода для каждой хранимой процедуры, которую я имею в системе. Один возвращает DbDataReader, а другой возвращает DataSet / DataTable. Методы, которые возвращают DataSet / DataTable, вызывают метод, возвращающий DbDataReader, а затем используют метод «Load» для DataTable или адаптер для заполнения набора данных. Иногда вам нужны DataSets, потому что вам, вероятно, придется каким-то образом переназначить данные или вам нужно запустить другой запрос, и если у вас не включен MARS, вы не можете открыть DbDataReader и запустить другой запрос.

Теперь есть некоторые проблемы с использованием DbDataReader или DataSet / DataTable, обычно это ясность кода, проверка времени компиляции и т. Д. Вы можете использовать классы-обертки для вашего datareader и фактически вы можете использовать свои DataReaders с IEnumerable с ними. Действительно крутая способность. Так что вы не только получаете строгую типизацию и читабельность кода, но и IEnumerable!

Так что класс может выглядеть следующим образом.

public sealed class BlogItemDrw : BaseDbDataReaderWrapper
{
    public Int64 ItemId { get { return (Int64)DbDataReader[0]; } }
    public Int64 MemberId { get { return (Int64)DbDataReader[1]; } }
    public String ItemTitle { get { return (String)DbDataReader[2]; } }
    public String ItemDesc { get { if (DbDataReader[3] != DBNull.Value) return (String)DbDataReader[3]; else return default(String); } }
    public DateTime ItemPubdate { get { return (DateTime)DbDataReader[4]; } }
    public Int32 ItemCommentCnt { get { return (Int32)DbDataReader[5]; } }
    public Boolean ItemAllowComment { get { return (Boolean)DbDataReader[6]; } }
    public BlogItemDrw()
      :base()
    {
    }

    public BlogItemDrw(DbDataReader dbDataReader)
      :base(dbDataReader)
    {
    }
}

Упаковщик DataReader

У меня есть запись в блоге (ссылка выше), которая более детально описана, и я буду делать генератор исходного кода для этого и другого кода уровня DataAccess.

Вы можете использовать ту же технику для DataTables (генератор кода создает код), чтобы вы могли обращаться с ними как со строго типизированной DataTable без дополнительных затрат, предоставляемых VS.NET из коробки.

Имейте в виду, что существует только один экземпляр класса-оболочки. Таким образом, вы не создаете сотни экземпляров класса только для того, чтобы выбросить его.

4 голосов
/ 08 октября 2008

Всегда помещайте ваши данные в классы, определенные для конкретного использования. Не передавайте DataSets или DataReaders.

4 голосов
/ 08 октября 2008

Если ваш сохраненный процесс возвращает несколько наборов, используйте DataReader.NextResult для перехода к следующему фрагменту данных. Таким образом, вы можете получить все свои данные, загрузить их в свои объекты и закрыть ридер как можно скорее. Это будет самый быстрый способ получить ваши данные.

3 голосов
/ 08 октября 2008

Сопоставьте DataReader с промежуточными объектами, а затем привяжите элементы управления с помощью этих объектов. В определенных обстоятельствах можно использовать DataSets, но таких случаев мало, если у вас есть веские причины для «просто получения данных». Что бы вы ни делали, не передавайте DataReader вашим элементам управления для привязки (не то, что вы сказали, что рассматривали это).

Мое личное предпочтение будет заключаться в использовании ORM, но если вы собираетесь вручную свернуть доступ к данным, я думаю, что вам следует предпочесть отображение DataReaders на объекты, а не на DataSets. Использование .NextResult в качестве способа ограничить себя от многократного попадания в базу данных, однако, является обоюдоострым мечом, поэтому выбирайте мудро. Вы обнаружите, что повторяетесь, если попытаетесь создать проки, которые всегда будут получать именно то, что вам нужно, используя только один вызов базы данных. Если ваше приложение занимает всего несколько страниц, это, вероятно, нормально, но все может быстро выйти из-под контроля. Лично я предпочел бы иметь одну процедуру для каждого типа объекта, а затем обращаться к базе данных несколько раз (по одному разу для каждого типа объекта), чтобы максимизировать удобство обслуживания. Вот где светит ORM, потому что хороший генерирует Sql, который в большинстве случаев даст вам именно то, что вы хотите, одним вызовом.

2 голосов
/ 03 июня 2010

Независимо от того, выбираете ли вы один набор результатов или несколько наборов результатов, консенсус, по-видимому, заключается в использовании DataReader вместо DataSet.

Что касается того, стоит ли вам когда-либо беспокоиться о множественных результирующих наборах, то мудрость заключается в том, что вы не должны этого делать, но я могу представить разумный класс исключений из этого правила: (тесно) связанный результирующие наборы. Вы, конечно, не хотите добавлять запрос, чтобы вернуть тот же набор вариантов для выпадающего списка, который повторяется на сотнях или даже десятках страниц в вашем приложении, но несколько узко используемых наборов могут быть разумно объединены. Например, в настоящее время я создаю страницу для отображения нескольких наборов «расхождений» для пакета данных ETL. Ни один из этих запросов, скорее всего, не будет использоваться где-либо еще, поэтому было бы удобно инкапсулировать их как единое целое «получить несоответствия». С другой стороны, лучшая производительность в этом случае может быть незначительной по сравнению с обходом естественной архитектуры набора результатов «один спрок» - одного набора ORM или свернутого вручную кода доступа к данным.

2 голосов
/ 08 октября 2008

Почти в каждой ситуации DataReader s - лучшее решение для чтения из базы данных. DataReader с быстрее и требуют меньше памяти, чем DataTable с или DataSet с.

Кроме того, DataSet s часто может привести к ситуациям, когда модель OO сломана . Это не очень объектно-ориентированная передача реляционных данных / схем вместо объектов, которые знают, как манипулировать этими данными.

Таким образом, из соображений расширяемости, масштабируемости, модульности и производительности всегда используйте DataReader s, если вы считаете себя настоящим программистом ™;)

Проверьте ссылки на факты и дискуссии о двух из них на практике и в теории.

2 голосов
/ 08 октября 2008

Если вы не заинтересованы в обновлении или удалении записей, извлеченных из базы данных, я бы предложил использовать DataReader В основном DataSet использует несколько Datareaders, поэтому DataReader должен дать вам хорошее преимущество в производительности.

1 голос
/ 08 октября 2008

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

Лично с несколькими раскрывающимися списками я обычно обращаюсь к отдельным фрагментам данных, чтобы получить их, а не к хранимой процедуре, которая возвращает 5 наборов результатов.

0 голосов
/ 08 октября 2008

Посмотрите на адаптеры таблиц, которые доступны с .NET 2.0 и выше. Что они делают, так это дают вам сильную типизированную DataTable и позволяют сопоставить с ней метод Fill, который будет использовать DataReader для его загрузки. Ваш метод заполнения может быть существующими хранимыми процедурами, вашим собственным AdHoc SQL или даже позволить мастеру создать AdHod или хранимую процедуру для вас.

Вы можете найти это, запустив новый объект XSD DataSet в своем проекте. Для таблиц, которые используются не только для поиска, вы также можете отобразить методы вставки / обновления / удаления в TableAdapter.

...