2016-02-04 49 views
0

我发送一个数据表的数据,它只是将数据插入到表中的存储过程,但我得到一个错误所有行会作为一个行存储过程C#

过程或函数usp_InsertData有太多许多参数被指定。

当我使用事件探查器来查看正在发生的事情时,我发现所有行都作为一行进入存储过程。

String strConnString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString; 
SqlConnection con = new SqlConnection(); 

public static void InsertData(DataTable dt) 
{ 
     String strConnString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString; 
     SqlConnection con = new SqlConnection(); 
     con.ConnectionString = strConnString; 

     SqlCommand cmd = new SqlCommand(); 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.CommandText = ("usp_InsertData"); 
     cmd.Connection = con; 

     con.Open(); 

     for (int i = 1; i < dt.Rows.Count; i++) 
     { 
      cmd.Parameters.AddWithValue("@FirstIssue", dt.Rows[i][0].ToString()); 
      cmd.Parameters.AddWithValue("@RTitle", dt.Rows[i][1].ToString()); 
      cmd.Parameters.AddWithValue("@RFirstName", dt.Rows[i][2].ToString()); 
      cmd.Parameters.AddWithValue("@RLastName", dt.Rows[i][3].ToString()); 
      cmd.Parameters.AddWithValue("@RAddress1", dt.Rows[i][4].ToString()); 
      cmd.Parameters.AddWithValue("@RAddress2", dt.Rows[i][5].ToString()); 
      cmd.Parameters.AddWithValue("@RAddress3", dt.Rows[i][6].ToString()); 
      cmd.Parameters.AddWithValue("@RCity", dt.Rows[i][7].ToString()); 
      cmd.Parameters.AddWithValue("@RZip", dt.Rows[i][8].ToString()); 
      cmd.Parameters.AddWithValue("@RCounty", dt.Rows[i][9].ToString()); 
      cmd.Parameters.AddWithValue("@RCountry", dt.Rows[i][10].ToString()); 
      cmd.Parameters.AddWithValue("@PTitle", dt.Rows[i][11].ToString()); 
      cmd.Parameters.AddWithValue("@PFirstName", dt.Rows[i][12].ToString()); 
      cmd.Parameters.AddWithValue("@PLastName", dt.Rows[i][13].ToString()); 
      cmd.Parameters.AddWithValue("@PAddress1", dt.Rows[i][14].ToString()); 
      cmd.Parameters.AddWithValue("@PAddress2", dt.Rows[i][15].ToString()); 
      cmd.Parameters.AddWithValue("@PAddress3", dt.Rows[i][16].ToString()); 
      cmd.Parameters.AddWithValue("@PCity", dt.Rows[i][17].ToString()); 
      cmd.Parameters.AddWithValue("@PZip", dt.Rows[i][18].ToString()); 
      cmd.Parameters.AddWithValue("@PCounty", dt.Rows[i][19].ToString()); 
      cmd.Parameters.AddWithValue("@PCountry", dt.Rows[i][20].ToString()); 
      cmd.Parameters.AddWithValue("@SubscriberAccountNumber", dt.Rows[i][21].ToString()); 
      cmd.Parameters.AddWithValue("@OnSaleDate", dt.Rows[i][22].ToString()); 
      cmd.Parameters.AddWithValue("@Subscriber", dt.Rows[i][23].ToString()); 

      try 
      { 
       cmd.ExecuteNonQuery(); 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 

     MessageBox.Show("data inserted"); 
     con.Close(); 
     con.Dispose(); 
    } 

有人可以告诉我如何解决这个问题?

+3

此代码应提高对第二回路异常。你不能第一次调用AddWithValue并且没有先清除集合 – Steve

+2

为什么你要这样做两次''SqlConnection con = new SqlConnection();'你也应该把所有的Sql对象包装在一个'using() {}'并将for循环放入使用中或将forloop分离出来放入单独的方法中... – MethodMan

+0

如果您想要一个简单的方法,它将利用正在执行的sql插入例如并解析参数我将发布一个简单的方法你可以使用它比你当前做的更清洁 – MethodMan

回答

3

当代码到达第二个循环时,您的代码会引发异常,因为该命令的参数集合已经填充了参数名称,并且再次调用具有相同名称的AddWithValue会引发该异常。

您可以在每个循环调用Parameters.Clear()方法,但更好的解决方案是在进入循环之前创建所有参数,然后在循环内设置当前行的值而不重新创建参数列表。

String strConnString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString; 
using(SqlConnection con = new SqlConnection(strConnString)) 
using(SqlCommand cmd = new SqlCommand("usp_InsertData", con)) 
{ 
    cmd.CommandType = CommandType.StoredProcedure; 
    con.Open(); 

    cmd.Parameters.Add("@FirstIssue", SqlDbType.NVarChar); 
    .... add the other parameters specifying the correct datatype ..... 

    for (int i = 1; i < dt.Rows.Count; i++) 
    { 
     cmd.Parameters["@FirstIssue"].Value = dt.Rows[i][0].ToString()); 
     ... other parameters values follows here .... 

     // If you don't use the exception don't catch it.... 
     cmd.ExecuteNonQuery(); 
    } 
} 

还要注意的是像连接和命令一次性对象应在使用块内创建,以确保适当关闭和异常

+1

优秀的解释@Steve特别是在'Parameters.Clear + 1'中,你可能想向OP解释为什么使用'using' vs显式调用close和dispose以及 – MethodMan

0

要添加参数,使用相同的钥匙的情况下,也处置每个循环的参数列表。

在循环结尾添加cmd.Parameters.Clear()语句以在下一个循环开始之前清除参数,然后它应该可以工作。

在附注中,代码中存在很多性能问题。

+0

哪种性能问题更好? –

+0

1)您可以在循环外创建参数,然后在循环内分配值。 2)你没有清除或销毁cmd对象。 3)如果可以修改存储过程,则可以修改它以接受整个数据表,而不是一次发送一行,如果数据表中有数百万行,则这会成为应用程序的开销。 – Phani