2017-05-19 14 views
0

我有一個存儲過程,我從後面的代碼調用(C#)有一個謎。我很困惑,因爲我在C#端添加了我的代碼的觀察點,並且所有內容似乎都具有應該對存儲過程調用的值,但是,該過程運行時沒有任何可以告訴的錯誤,但我的表沒有得到我感覺他們應該的值的更新。調用存儲過程不按預期更新

SP獲取傳遞給它的三個值。

Record ID (@Record_ID), Column to update (@UpdColumn), and the value to place in that column (@UpdValue).

這裏是我的SP,我呼籲:

ALTER PROCEDURE [dbo].[Single_Col_Update] 
-- Add the parameters for the stored procedure here 
@Record_ID INT, 
@UpdColumn CHAR, 
@UpdValue NVARCHAR 
AS 
BEGIN 
SET NOCOUNT ON; 

IF @UpdColumn = 'TicketNumber' 
    UPDATE dbo.csr_refdata_ip360_HostVulnerabilityCSV 
    SET TicketNumber = @UpdValue 
    WHERE RecID = @Record_ID; 

IF @UpdColumn = 'TicketClosed' 
    UPDATE dbo.csr_refdata_ip360_HostVulnerabilityCSV 
    SET TicketClosed = @UpdValue 
    WHERE RecID = @Record_ID; 

IF @UpdColumn = 'Notes' 
    UPDATE dbo.csr_refdata_ip360_HostVulnerabilityCSV 
    SET Notes = @UpdValue 
    WHERE RecID = @Record_ID; 

IF @UpdColumn = 'Exception_ID' 
    UPDATE dbo.csr_refdata_ip360_HostVulnerabilityCSV 
    SET ExceptionID = @UpdValue 
    WHERE RecID = @Record_ID; 
END 

這裏是代碼段調用SP:

foreach (string record in recordnumber) 
{ 
SqlConnection con = new SqlConnection("Data Source=MyDataSource"); 
SqlCommand cmd = new SqlCommand(); 

cmd.CommandText = "Single_Col_Update"; 
cmd.CommandType = CommandType.StoredProcedure; 
cmd.Connection = con; 

cmd.Parameters.AddWithValue("@Record_ID", Convert.ToInt32(record)); 
cmd.Parameters.AddWithValue("@UpdColumn", Session["UpdColumn"]); 
cmd.Parameters.AddWithValue("@UpdValue", Session["UpdValue"]); 

con.Open(); 
cmd.ExecuteNonQuery(); 
con.Close(); 
} 

由於所有的變量是對的,我米不知道爲什麼這不更新。希望你們中的一些人在這裏看到一個錯誤。

UPDATED 2017/5/19 1:40 PM Central - Steve, 我試圖執行以下規定的調用。我只對您提供的內容進行了修改:

  1. 'cmd.Parameters.Add(「@ UpdValue」,SqlDbType.NVarChar,1024);' //而不是255,因爲我在那裏提供的列是一個NVarChar(MAX),我可能不得不返回並修改它大於1024.似乎沒有可以放入的最大值那麼測試1024就足夠了。
  2. 省略了'transaction.Rollback();' //我對「交易」這個詞保持了紅色的內容,儘管我嘗試了我無法驗證它。

底線是在執行下面的代碼後,結果與以前完全一樣。代碼執行時不會通過我添加的Consol.Write或通過VS 2017 IDE報告任何錯誤。

SqlTransaction transaction; 
try 
{ 
    using (SqlConnection con = new SqlConnection("Data Source=MyDataSource")) 
    using (SqlCommand cmd = new SqlCommand("Single_Col_Update", con)) 
    { 
     con.Open(); 
     transaction = con.BeginTransaction(); 
     cmd.Transaction = transaction; 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.Parameters.Add("@Record_ID", SqlDbType.Int); 
     cmd.Parameters.Add("@UpdColumn", SqlDbType.NVarChar, 255); 
     cmd.Parameters.Add("@UpdValue", SqlDbType.NVarChar, 1024); 

     foreach (string record in recordnumber) 
      { 
       cmd.Parameters["@Record_ID"].Value = Convert.ToInt32(record); 
       cmd.Parameters["@UpdColumn"].Value = Session["UpdColumn"].ToString(); 
       cmd.Parameters["@UpdValue"].Value = Session["UpdValue"].ToString(); 
       cmd.ExecuteNonQuery(); 
      } 

     transaction.Commit(); 
    } 
} 
catch (Exception ex) 
{ 
    Console.Write(ex.ToString()); 
} 

所以我仍然在那裏,但我注意到了你分享的內容,我同意你所說的。我沒有注意到,我正在打開和關閉那裏的連接,並沒有意識到你分享的其他東西。

但是這個窘境依然存在!

更新05/22/2017 10:45 AM中心時間: 我意識到我試圖在我的存儲過程中將NVarchar類型填充到Varchar類型中。一旦糾正,我根據史蒂夫的反饋做出的修改工作得很好。我還沒有嘗試過,但我假設如果類型匹配開始的話,我必須從頭開始,但史蒂夫的例子​​更加清晰,所以我甚至沒有回去測試舊的方式。再次感謝史蒂夫!

+0

將* size *添加到字符數據類型,例如, '@UpdColumn CHAR(64)', –

+0

還有,當你正在更新時,你是否需要發出任何'顯式的Commit'命令..?你有沒有嘗試將會話變量轉換爲其確切的數據類型..以及..?嘗試在'try {} catch(SqlException sqlEx)周圍包裝'cmd.ExecuteNonQuery' {}'同樣你的連接字符串看起來也很有趣.. – MethodMan

+2

不要在循環內創建con/cmd,在外部創建它們覆蓋循環內的參數(通過顯式創建它們)。 –

回答

0

只有當列是固定長度時才應使用CHAR。當你使用不同長度的字符串時,結果通常不會如你所期望的那樣,因爲參數/列會被填充空格,這就是爲什麼你的IF語句失敗。

請勿對@UpdColumn使用CHAR類型。使用NVARCHAR來代替這個列,並且最好在存儲過程中爲這個參數和UpdValue參數指定一個長度,然後在從你的C#代碼中調用存儲過程時緊密地匹配它。

+0

根據Steve的回覆,CHAR被修改爲NVARCHAR。 –

2

的問題是在這個參數

@UpdColumn CHAR, 

這樣的存儲過程只需要一個字符,而不是字符串的聲明。
因此,所有的if語句是假的,什麼都不會被它更新

更改爲

@UpdColumn NVARCHAR(255) 

同樣是爲@UpdValue參數真以下。同樣,存儲過程只接收一個字符。如果你傳遞整個字符串,這並不重要。
如果不指定NVARCHAR或CHAR參數的大小,數據庫引擎將只使用傳遞值的第一個字符。

我也想強調Alex K.上面的註釋,雖然它不應該給你很多收益,但最好打開連接並使用循環外的參數創建命令。在循環內部只是改變參數的值,並執行SP

SqlTransaction transaction; 
try 
{ 
    using(SqlConnection con = new SqlConnection(.....)) 
    using(SqlCommand cmd = new SqlCommand("Single_Col_Update", con)) 
    { 
     con.Open(); 
     transaction = con.BeginTransaction()) 
     cmd.Transaction = transaction; 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.Parameters.Add("@Record_ID", SqlDbType.Int); 
     cmd.Parameters.Add("@UpdColumn", SqlDbType.NVarChar, 255); 
     cmd.Parameters.Add("@UpdValue", SqlDbType.NVarChar, 255); 
     foreach (string record in recordnumber) 
     { 
      cmd.Parameters["@Record_ID"].Value = Convert.ToInt32(record)); 
      cmd.Parameters["@UpdColumn"].Value = Session["UpdColumn"].ToString(); 
      cmd.Parameters["@UpdValue"].Value = Session["UpdValue"].ToString(); 
      cmd.ExecuteNonQuery(); 
     } 
     transaction.Commit(); 
    } 
} 
catch(Exception ex) 
{ 
    // show a message to your users 
    transaction.Rollback(); 
} 

我還添加了所有你的循環在事務中確認所有插入作爲一個整體或拒絕在錯誤的情況下所有。