Как выполнить хранимую процедуру несколько раз в С#

У меня есть приложение для учета рабочего времени, в котором пользователи вводят время входа/выхода в разные дни недели. Форма обрабатывает входящие и исходящие данные каждый день, заносит их в качестве параметров в хранимую процедуру и добавляет в базу данных. Как мне сделать это наиболее эффективно? У меня нет доступа к БД, только к хранимым процедурам.

Это голый код, я удалил некоторые ненужные коды.

SqlConnection conn = new SqlConnection(connString);
conn.Open();
SqlCommand cmd = new SqlCommand("insertINOUT", conn);
cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add(new SqlParameter("@UserName", user));

for (int j = 0; j < weekDays.Length; j++)
{
    cmd.Parameters.Add(new SqlParameter("@In", in));
    cmd.Parameters.Add(new SqlParameter("@Out", out));
    cmd.ExecuteReader();
}
conn.Close();

Код работает, если есть только 1 день входа/выхода. Если пользователи заполняют несколько дней, я получаю эту ошибку: Параметр '@In' был указан несколько раз.

Спасибо за вашу помощь.


person dam    schedule 13.09.2011    source источник
comment
Это все из-за этих операторов new в цикле for. Вы пытаетесь сделать new из того, что уже существует.   -  person Brad    schedule 13.09.2011


Ответы (4)


SqlConnection conn = new SqlConnection(connString);
conn.Open();
SqlCommand cmd = new SqlCommand("insertINOUT", conn);
cmd.CommandType = CommandType.StoredProcedure;

for (int j = 0; j < weekDays.Length; j++)
{
    **cmd.Parameters.Clear();**
    cmd.Parameters.Add(new SqlParameter("@UserName", user));
    cmd.Parameters.Add(new SqlParameter("@In", in));
    cmd.Parameters.Add(new SqlParameter("@Out", out));
    cmd.ExecuteReader();
}
conn.Close();

(Вы должны очищать параметры на каждой итерации.)

person Kyle W    schedule 13.09.2011

В качестве альтернативы вы можете изменить область SqlCommand, чтобы она каждый раз создавалась заново.

SqlConnection conn = new SqlConnection(connString);
conn.Open();

for (int j = 0; j < weekDays.Length; j++)
{
    SqlCommand cmd = new SqlCommand("insertINOUT", conn);
    cmd.CommandType = CommandType.StoredProcedure;

    cmd.Parameters.Add(new SqlParameter("@UserName", user));
    cmd.Parameters.Add(new SqlParameter("@In", in));
    cmd.Parameters.Add(new SqlParameter("@Out", out));
    cmd.ExecuteReader();
}
conn.Close();

Кажется немного расточительным, но есть некоторые библиотеки, которые работают таким образом (на ум приходит Enterprise Library DAAB).

person mgnoonan    schedule 13.09.2011

Это потому, что вы пытались повторно добавить одни и те же параметры к тому же объекту sqlcommand. Для лучшей производительности ПЕРЕД запуском цикла for откройте соединение и добавьте параметры без значений. Затем ВНУТРИ вашего цикла for все, что вы делаете, это устанавливаете значение параметров, а затем выполняете процедуру. Не нужно пересоздавать сами параметры на каждой итерации цикла, вы просто сжигаете ресурсы впустую. Попробуй это:

string strCon = "Your Connection String Here";
using (SqlConnection conSQL = new SqlConnection(strCon))
{
    conSQL.Open();
    using (SqlCommand cmdSQL = new SqlCommand())
    {
        cmdSQL.CommandType = CommandType.StoredProcedure;
        cmdSQL.CommandText = "The Name of Your Stored Procedure Here";
        cmdSQL.Connection = conSQL;
        // I'm just going to assume that the data type for the
        // parameters is nvarchar and that both are input parameters...
        // Just for demonstration purposes
        cmdSQL.Parameters.Add("@In", SqlDbType.NVarChar, 50);
        cmdSQL.Parameters.Add("@Out", SqlDbType.NVarChar, 50);
        for (var j = 0; j <= weekDays.Length - 1; j += 1)
        {
            cmdSQL.Parameters("@In").Value = strIn;
            cmdSQL.Parameters("@Out").Value = strOut;
            // I'm not sure why in your code you put ExecuteReader here.
            // You don't show that you're using the reader at all, rather
            // it looks like you are actually just trying to execute the procedure without
            // using any type of return parameter values or a reader.
            // So I changed the code here to be what it should be if that is true.
            cmdSQL.ExecuteNonQuery();
        }
    }
    conSQL.Close();
}

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

person Wizard's Enterprise    schedule 24.05.2021

Причина, по которой вы получаете эту ошибку, заключается в том, что цикл for повторно добавляет параметр несколько раз:

cmd.Parameters.Add(new SqlParameter("@In", in));
cmd.Parameters.Add(new SqlParameter("@Out", out));

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

person Icarus    schedule 13.09.2011