如何在C#中多次执行存储过程

6
我有一个时间表应用程序,用户可以输入每周不同日期的上下班时间。该表单将每天的上下班时间处理为参数,传递给一个存储过程并添加到数据库中。我如何最有效地完成这个任务?我没有访问数据库的权限,只能使用存储过程。
以下是代码的基本框架,已删除一些不必要的代码。
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();

如果只有一天的进出情况,这段代码可以正常运行。但是如果用户填写了多天,请看到以下错误提示:参数“@In”被多次提供。

感谢您的帮助。


这都是因为 for 循环中的那些 new 语句。你试图对已经存在的东西进行 new 操作。 - Brad
6个回答

17
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();

(您需要在每次迭代中清除参数。)


1

这是因为您试图将相同参数重新添加到同一个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();
}

我知道这个问题已经被问了好几年,但我想仍会有人在搜索并且可能会发现这个答案有帮助。


1

另一种选择是,您可以更改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();

看起来有点浪费,但是有一些库是这样工作的(企业库 DAAB 就是其中之一)。


1
using (SqlConnection conn ... )
{
    SqlCommand cmd = ...
    ...
    // Set up the parameter list.
    //   You can use   .AddWithValue   here to add values that don't change in the loop.
    cmd.Parameters.Add("@Username", SqlDbType.VarChar);
    ...
    for (...)
    {
        // Load one set of loopy values.
        cmd.Parameters["@UserId"].Value = user;
        ...
    }
}

0
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"+j, in));
        cmd.Parameters.Add(new SqlParameter("@Out"+j, out));
        cmd.ExecuteReader();
    }
    conn.Close();

0
你之所以会收到那个错误是因为for循环多次重新添加了参数。
cmd.Parameters.Add(new SqlParameter("@In", in));
cmd.Parameters.Add(new SqlParameter("@Out", out));

正确的做法是在 for 循环的最后一行清除 Parameters 集合,或者仅检查参数是否已经存在并设置其值,而不是使用 Parameters.Add


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接