Sql запрос с параметрами в цикле для добавления данных в базу

124
11 ноября 2019, 00:20

Сделал такую конструкцию, для добавления данных в базу, вопрос, Правильно ли написан запрос, и если учитывать то, что это цикл, будет ли эффективным такое решение?

using (SqlConnection connection =new SqlConnection(connextionstring))
        {
            SqlCommand command =new SqlCommand("DELETE FROM Class1", connection);
            connection.Open();
            command.ExecuteNonQuery();
            SqlCommand command2 = new SqlCommand("DELETE FROM Class2", connection);
            command2.ExecuteNonQuery();
            SqlCommand command3 = new SqlCommand("DELETE FROM Class3", connection);
            command3.ExecuteNonQuery();
            SqlCommand command4 = new SqlCommand("DELETE FROM Class4", connection);
            command4.ExecuteNonQuery();
            SqlCommand command5 = new SqlCommand("DELETE FROM Class5", connection);
            command5.ExecuteNonQuery();
             Class1 contactMary = ObjectSpace.FindObject<Class1>();
            foreach (var VARIABLE in mass2)
            {
            String[] words = VARIABLE.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            var a= contactMary.METHODID = Convert.ToInt16(words[0]);
            var b= contactMary.DESCRIPTION = words[1];
            var c= contactMary.METHODTYPEID = words[2];
            var d= contactMary.TEXTDESCRIPTION = words[3];
            SqlCommand command6 = new SqlCommand("INSERT INTO Class1 (METHODID, DESCRIPTION, METHODTYPEID, TEXTDESCRIPTION) VALUES (@a, @b, @c, @d)", connection);
            command6.Parameters.AddWithValue("@a",a);
            command6.Parameters.AddWithValue("@b",b);
            command6.Parameters.AddWithValue("@c",c);
            command6.Parameters.AddWithValue("@d",d);
            command6.ExecuteNonQuery();
            }
Answer 1

Во-первых, всем переменным нужно давать говорящие имена. command2, command3 - глядя на их имена, что можно предположить о них? Что делают эти команды? Непонятно...

Можно назвать, например, так: deleteClass2Command, deleteClass3Command - при этом сразу ясно, для чего они предназначены.

Имена таблиц в базе данных, кстати, тоже хорошо бы переименовать. Потому как Class1 мало о чём говорит.

Освобождать (диспозить) нужно не только соединение, но и все команды. Т. е. их тоже нужно обернуть в using.

using (var deleteClass2Command = new SqlCommand("DELETE FROM Class1", connection))
{ .... }

Идём дальше. В принципе, вовсе необязательно использовать несколько команд. Достаточно одной переопределять запрос.

connection.Open();
using (var deleteCommand = new SqlCommand("DELETE FROM Class1", connection))
{
    deleteCommand.ExecuteNonQuery();
    deleteCommand.CommandText = "DELETE FROM Class2";
    deleteCommand.ExecuteNonQuery();
    deleteCommand.CommandText = "DELETE FROM Class3";
    deleteCommand.ExecuteNonQuery();
    // и т. д.
}

Тут имя команды является общим для всех, поэтому оно без уточнения, к какой таблице относится.

Далее. Название переменной contactMary - хорошее. И регистр правильно набран, в соответствии с гайдами. Правда, совершенно неясно, зачем оно нужно.

А вот mass2 - плохо. Вероятно это массив (по-английски array). Массив чего? Что в нём содержится, какие объекты?

VARIABLE - совсем плохо. Слово variable означает переменная и только. И оно не должно быть большими буквами.

Использование метода AddWithValue может привести к проблемам с производительностью. Советую ознакомиться: Can we stop using AddWithValue() already?. Лучше явно указывать типы данных в колонках. Укажите именно те значения перечисления SqlDbType, которые в таблице БД.

using (var insertCommand = new SqlCommand(
        "INSERT INTO Class1 (METHODID, DESCRIPTION, METHODTYPEID, TEXTDESCRIPTION) " +
        "VALUES (@id, @desc, @typeId, @textDesc)",
        connection))
{
    foreach (var item in someCollection)
    {
        String[] words = item.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
        var id = Convert.ToInt16(words[0]);
        var desc = words[1];
        var typeId = words[2];
        var textDesc = words[3];
        insertCommand.Parameters.Add("@id", SqlDbType.SmallInt).Value = id;
        insertCommand.Parameters.Add("@desc", SqlDbType.NVarChar).Value = desc;
        insertCommand.Parameters.Add("@typeId", SqlDbType.NVarChar).Value = typeId;
        insertCommand.Parameters.Add("@textDesc", SqlDbType.NVarChar).Value = textDesc;
        insertCommand.ExecuteNonQuery();
    }
}

Создание команды я вынес из цикла: незачем на каждой итерации её пересоздавать.
Опять же, изменил имена параметров. Тут можно упрекнуть меня в том, что они слишком короткие, малоговорящие... Ну дык, разглагольствовать мы все горазды, а набивать длинный код неохота... :)

И напоследок, нужно добавить обработку исключений и проверку возвращаемых значений метода ExecuteNonQuery.

READ ALSO
Алгоритм работы Windows аутентификации в веб

Алгоритм работы Windows аутентификации в веб

Как работает в Windows аутентификации в вебе

121
Структура объектов Unity C#

Структура объектов Unity C#

У меня есть игра, в которой есть разный муссорОни обладают полями типа: - тип (как индикатор, который указывает на то какие параметры будут...

106
Создание библиотеки DLL на C++ по примеру C#

Создание библиотеки DLL на C++ по примеру C#

Есть инструкция по написании необходимой библиотеки на C#Она гласит следующее:

111
C++ clr Hosting - ICLRMetaHost GetRuntime уточнение версии до 4.7.2

C++ clr Hosting - ICLRMetaHost GetRuntime уточнение версии до 4.7.2

При использовании конфигурации appexe

93