0

我正在尝试从一个表中检索记录列表,然后写入另一个表。我使用一个简单的查询将值检索到 SqlDataReader,然后将它们加载到 DataTable。使用 DataTableReader ,我将浏览保存在 DataTable 中的整个数据集。问题是,在读取每条记录时,我试图使用存储过程将这些值插入到另一个表中。但它只插入第一行值,并且对于第二行开始给出一些异常说法。“过程或函数指定了太多参数”


string ConStr = ConfigurationManager.ConnectionStrings["ConString"].ConnectionString;
SqlConnection NewCon = new SqlConnection(ConStr);
NewCon.Open();

SqlCommand NewCmd3 = NewCon.CreateCommand();
NewCmd3.CommandType = CommandType.Text;
NewCmd3.CommandText ="select * from dbo.Request_List where  group_no ='" +group_no+      "'";
NewCon.Close();
NewCon.Open(); 
SqlDataReader dr = (SqlDataReader)NewCmd3.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
DataTableReader reader = new DataTableReader(dt);

NewCmd.Dispose();
NewCon.Close();
NewCon.Open();

SqlCommand NewCmdGrpReqSer = NewCon.CreateCommand();
NewCmdGrpReqSer.CommandType = CommandType.StoredProcedure;
NewCmdGrpReqSer.CommandText = "Voucher_Request_Connection";
if (reader.HasRows)
{
    int request_no = 0;
    while (reader.Read())
    {
        request_no = (int)reader["request_no"];
        NewCmdGrpReqSer.Parameters.Add("@serial_no", serial_no);
        NewCmdGrpReqSer.Parameters.Add("@request_no", request_no);
        try
        {
            NewCmdGrpReqSer.ExecuteNonQuery();
            MessageBox.Show("Connection Updated");//just to check the status.tempory 
        }
        catch (Exception xcep)
        {
            MessageBox.Show(xcep.Message);
        }
        MessageBox.Show(request_no.ToString());// 
    }
    NewCmdGrpReqSer.Dispose();
    NewCon.Close();
}

任何解决方案?

4

2 回答 2

3

正如@Sparky 建议的那样,问题在于您继续向插入命令添加参数。但是,还有其他几种方法可以改进代码。这些改进将消除清除参数的需要,并有助于确保您不会留下一次性资源未处置。

首先 - 使用using您的一次性物品的声明。这消除了对显式关闭的需要(顺便说一句,连接只需要关闭/处置之一,因为我相信处置调用关闭)。其次,只需为每次插入创建一个新命令。这将防止围绕重置参数的复杂逻辑以及可能处理命令的错误状态。第三,检查插入的结果,确保插入成功。第四,显式捕获 SqlException - 您不想在代码中意外隐藏意外错误。如果有必要确保所有异常都不会冒泡,请考虑使用多个异常处理程序并为每种情况“做正确的事情” - 例如使用不同的错误级别或类别进行日志记录,中止整个操作而不仅仅是此插入等。 最后,我会使用更好的变量名。特别是,避免将数字标识符附加到通用变量名称。这使得代码更难理解,无论是对于其他人还是对于您在您让代码搁置一段时间后的您自己。

这是我的版本。请注意,我可能会做其他几件事,例如将字符串文字转换为适当命名的常量。在 ConfigurationManager 对象周围引入一个强类型的包装器,以使测试更容易。从变量名称中删除下划线并改用 camelCase。尽管这些在本质上更具风格,但您可能也需要考虑它们。

var connectionString = ConfigurationManager.ConnectionStrings["ConString"].ConnectionString;
using (var newConnection = new SqlConnection(connectionString))
{
    newConnection.Open();

    using (var selectCommand = newConnection.CreateCommand())
    {
        selectCommand.CommandType = CommandType.Text;
        select.CommandText ="select request_no from dbo.Request_List where group_no = @groupNumber";
        selectCommand.Parameters.AddWithValue("groupNumber", group_no);

        using (dataReader = (SqlDataReader)newCommand.ExecuteReader())
        {
            while (reader.HasRows && reader.Read())
            {
                using (var insertCommand = newConnection.CreateCommand())
                {
                    insertCommand.CommandType = CommandType.StoredProcedure;
                    insertCommand.CommandText = "Voucher_Request_Connection";

                    var request_no = (int)reader["request_no"];
                    insertCommand.Parameters.Add("@serial_no", serial_no);
                    insertCommand.Parameters.Add("@request_no", request_no);
                    try
                    {
                         if (insertCommand.ExecuteNonQuery() == 1)
                         {
                             MessageBox.Show("Connection Updated");//just to check the status.tempory 
                         }
                         else
                         {
                             MessageBox.Show("Connection was not updated " + request_no);
                         }
                    }
                    catch (SqlException xcep)
                    {
                        MessageBox.Show(xcep.Message);
                    }
                    MessageBox.Show(request_no.ToString());// 
                }
            }
        }
    }
}
于 2013-09-02T16:58:22.593 回答
1

尝试每次清除参数...

while (reader.Read())
{
request_no = (int)reader["request_no"];

//  Add this line
NewCmdGrpReqSer.Parameters.Clear();

NewCmdGrpReqSer.Parameters.Add("@serial_no", serial_no);
NewCmdGrpReqSer.Parameters.Add("@request_no", request_no);
try
{
于 2013-09-02T16:25:22.427 回答