Подтвердить что ты не робот

Когда следует использовать "SqlDbType" и "размер" при добавлении параметров SqlCommand?

Возникает связанный с этим вопрос:

Какой лучший способ передать параметры SQLCommand?

Но я хочу знать, что такое различия, и если есть какие-то проблемы с разными способами.

Я обычно использую структуру что-то вроде этого:

using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(SQL, conn))
{
     cmd.CommandType = CommandType.Text;
     cmd.CommandTimeout = Settings.Default.reportTimeout;
     cmd.Parameters.Add("type", SqlDbType.VarChar, 4).Value = type;

     cmd.Connection.Open();

     using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
     {
         adapter.Fill(ds);
     }
      //use data                    
}

Теперь есть несколько способов добавить параметры cmd, и мне интересно, что лучше:

cmd.Parameters.Add("@Name", SqlDbType.VarChar, 20).Value = "Bob";
cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = "Bob";
cmd.Parameters.Add("@Name").Value = "Bob";
cmd.Parameters.AddWithValue("@Name", "Bob");

Имея длину поля при передаче varchars, я предполагаю, что это не предпочтительнее, поскольку это волшебное значение, которое может быть изменено позже в базе данных. Это верно? Это вызывает любую проблему, передающую varchar таким образом (производительность или другое), я предполагаю, что по умолчанию используется varchar (max) или эквивалент базы данных. Я достаточно рад, что это сработает.

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

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

4b9b3361

Ответ 1

По моему опыту, я бы удостоверился, что я это делаю:

  • убедитесь, что он определяет тип данных для параметра. ADO.NET делает приличную работу при угадывании, но в некоторых случаях это может быть ужасно отключено - поэтому я бы избегал этого метода:

    cmd.Parameters.Add("@Name").Value = "Bob";
    cmd.Parameters.AddWithValue("@Name", "Bob");
    

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

    Просто будьте явным - скажите, какой тип вы хотите!

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

    cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = "Bob";
    

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

Итак, в вашем случае единственный подход, который действительно работает для меня, - это здесь:

cmd.Parameters.Add("@Name", SqlDbType.VarChar, 20).Value = "Bob";

потому что он a) определяет тип данных для использования явно, и b) явно определяет длину строки.

Ответ 2

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

Здесь цитата из MSDN:

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

Подробнее читайте в Кэширование и повторное использование плана выполнения.