Michael Breeden Ответов: 4

Набор против объекта DataReader


Что это было, примерно в 2002 году .Net дал нам DataAdapter/DataSet и DataReader. Все, что нам нужно было знать тогда, это то, что DataReader был самым быстрым.
Ну, это 14 лет спустя в корпоративной производственной среде после того, как мы должны были использовать хранимые процедуры после всех боев за предотвращение SQL-инъекции. ... Кстати, это служба Windows, никаких веб-вложений нигде нет.
Иногда нам нужно динамически генерировать SQL, поэтому нет никакого способа использовать хранимую процедуру, но в этом случае я потенциально мог бы, возможно. Это было бы хлопотно, но я мог бы сделать это... с ограничениями... потому что с помощью DataReader я перестаю читать строки, когда нахожу достаточно для обработки, которые имеют определенные критерии. Позже это станет еще более важным в будущем, поскольку разные записи получают разный приоритет (планируемая функция). Я подозреваю, что когда/если администратор БД поймет, что я использую DataReader с строковым литералом SQL, он выйдет из себя (он придирчив).
Поэтому мой вопрос будет таким
(1) Есть ли какие-либо новые последствия для рассмотрения использования DataReader, на которые я должен обратить внимание.
(2) Как я могу защитить свое решение о том, что мне нужна гибкость, если парень уходит?

Спасибо, М

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

Что я уже пробовал:

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

4 Ответов

Рейтинг:
2

F-ES Sitecore

Используйте EntityFramework, он должен дать вам то, что вам нужно. Под прикрытием он разрабатывает динамический SQL, необходимый для выполнения вашего запроса, и выполняет его за вас, абстрагируя все фактические данные доступа к данным. Это в основном заставляет ваши SQL-таблицы вести себя как объекты\списки в вашем коде (чрезмерное упрощение, но вы понимаете идею). Хотя это означало бы бросить SPs.


Рейтинг:
2

Mehdi Gholam

Лично я думаю, что это плохая идея-разделить вашу логику, поместить ее в слой базы данных и использовать хранимые процедуры, отличные от соображений производительности при обработке большого количества строк, по нескольким причинам:
1) I усложняет разработку и изменения, и вам приходится "массировать" свою логику, чтобы работать в хранимых процедурах (а это не то, для чего она была предназначена).
2)Вы заперты в своей базе данных поставщиков и не можете легко перейти к другой.
3) по крайней мере, в моих тестах использование обычного sql-кода было быстрее, чем использование хранимых процессов в любой БД post 2005.


Michael Breeden

>>> 3) По крайней мере, в моих тестах использование обычного sql-кода было быстрее, чем использование хранимых процессов в любой БД post 2005.;
Интересно, я слышал, что они были очень похожи, возможно, с краем хранимой процедуры. Тем не менее, из-за прошлых рисков SQL-инъекции некоторые магазины категорически запрещают использовать SQL-операторы вместо хранимых процедур... Я даже не использую параметры, поэтому просто надеюсь, что никто не заметит.

Mehdi Gholam

Существуют известные способы обойти атаки SQL-инъекций, но я предпочитаю иметь максимальную скорость разработки и гибкость, которая в краткосрочной и долгосрочной перспективе сводится к стоимости разработки.

Jörgen Andersson

Если вы знаете, что делаете, то нет никакой разницы между хранимыми процедурами и использованием простого SQL. И там не должно быть.
Наиболее распространенная причина, по которой SP работает быстрее, заключается в том, что план кэшируется, но если вы используете параметры с определенными размерами, ваш простой SQL также будет использовать кэш.
Наиболее распространенной причиной того, что SP работает медленнее обычного SQL, является использование динамических запросов. Тогда составленный план хорош только для определенного набора параметров. Одним из решений является использование опции WITH RECOMPILE при вызове SP.

Michael Breeden

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

Рейтинг:
11

Foothill

Очень простой подход к этому заключается в использовании параметризованных запросов для вашего динамического SQL

// brief example of what I use all over the place
public DataTable LoadRecords(DateTime pStartDate, DateTime pEndDate)
{
 DataTable results = new DataTable();
 // parameterized query
 string sqlStatement = "SELECT R.One, R.Two, R.Three FROM dbo.Records AS R WHERE R.Date BETWEEN @StartDate AND @EndDate;";

 using (SqlConnection conn = new SqlConnection(_connectionString))
 {
  conn.Open();

  using (SqlCommand command = new SqlCommand(sqlStatement, conn))
  {
   command.Parameters.Add("@StartDate", SqlDbType.DateTime).Value = pStartDate;
   command.Parameters.Add("@EndDate", SqlDbType.DateTime).Value = pEndDate;

   using (SqlDataReader reader = command.ExecuteReader())
   {
    results.Load(command);
   }
  }
 }

 return results;
}

Команда автоматически построит динамический оператор в параметризованный запрос, который устраняет угрозу SQL-инъекции.


Michael Breeden

Круто, это здорово. Он позволяет мне использовать параметры, но только тогда, когда я этого хочу. Это очень легко адаптируется.

Рейтинг:
1

OriginalGriff

DataReader не "быстрее", он просто откладывает" загрузку " записей до тех пор, пока вы не попросите их, что возвращает подход DataTable / DataSet, когда полный набор записей собран и возвращен в ваш код. DataReader занимает столько же времени - или даже больше - для обработки всех записей, потому что он распределяет время, которое подход DataTable помещает все вперед. Кроме того, для этого требуется соединение, открытое дольше (срок службы считывателя), и "свиньи" серверные ресурсы, которые DataTable подход освобождает немедленно. Который является, почему ваш администратор собирается "перевернуть".

И если вам нужны только двадцать лучших записей, то извлекайте только двадцать лучших строк, используя SELECT TOP 20 MyColumn1, MyColumn2, ... синтаксис. Это эффективно и быстрее!

Цитата:
нам нужно динамически генерировать SQL, поэтому нет никакого способа использовать хранимую процедуру
С каких это пор? SP по-прежнему могут использовать EXEC для выполнения динамически генерируемого SQL...


Michael Breeden

>> & gt;Для этого требуется соединение, открытое дольше (срок службы считывателя) и" свиньи " серверных ресурсов << & lt;
Это ключевая вещь, которая меня беспокоила, и почему код для использования DataAdapter только закомментирован, а не удален. Я могу даже сделать то, что используется настраиваемым.
Что касается "select top 20", то это обработка на номер факса. Я мог бы получить 100 записей с одним и тем же номером факса, но я разрешаю только 3 в своей системе одновременно. Это означает, что только 1 из 100 факсимильных линий может быть использована до тех пор, пока я не получу записи с разными номерами факсов. Мне нужно было бы заявление что-то вроде "select top(100) faxnumber is distinct" ... возможно, придется спросить у здешнего DBA, можно ли это сделать... может быть, групповое предложение... Хммм.
Я подозреваю, что использование оператора "exec" также может вызвать у кого-то крутящий момент.