2016-02-04 51 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