![](/img/trans.png)
[英]String or binary data would be truncated. The statement has been terminated?8
[英]Executing SqlCommand fails due to “string or binary data would be truncated. the statement has been terminated” error
我試圖將在DevExpress的GridView中進行的更改保存到數據庫的表中,並且能夠使用以下代碼來完成此操作:
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings[2].ConnectionString))
{
con.Open();
GridView gv = sender as GridView;
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandText = "UPDATE dbo.tb_Alumno set " + e.Column.FieldName + " = '" + e.Value + "' where pk_alumno = " + gv.GetRowCellValue(gv.FocusedRowHandle, gv.Columns[0]);
cmd.ExecuteNonQuery();
}
}
自從我添加了參數命令以防止SQL注入以來,我一直遇到這個問題。 我已經對每個參數的值進行了硬編碼,以遇到提供錯誤的參數,並且是@val
參數:
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings[2].ConnectionString))
{
con.Open();
GridView gv = sender as GridView;
using (SqlCommand cmd = con.CreateCommand())
{
#region Parameters
//cmd.CommandText = "UPDATE dbo.tb_Alumno set " + e.Column.FieldName + " = '" + e.Value + "' where pk_alumno = " + gv.GetRowCellValue(gv.FocusedRowHandle, gv.Columns[0]);
cmd.CommandText = "UPDATE dbo.tb_Alumno set @col = @val where pk_alumno = @id";
cmd.Parameters.AddWithValue("@col", e.Column.FieldName);
cmd.Parameters.AddWithValue("@val", e.Value);
//cmd.Parameters["@val"].SqlDbType = SqlDbType.VarChar;
cmd.Parameters.AddWithValue("@id", gv.GetRowCellValue(gv.FocusedRowHandle, gv.Columns[0]));
#endregion
try
{ cmd.ExecuteNonQuery(); }
catch (Exception xe)
{ MessageBox.Show(xe.Message); }
}
}
我可以提供的附加信息:
例如,如果我使用以下參數,它將引發相同的錯誤:
cmd.Parameters.AddWithValue("@col", "name");
cmd.Parameters.AddWithValue("@val", "More than 6 characters");
cmd.Parameters.AddWithValue("@id", 1);
這發生在所有領域
如果我將中線更改為以下內容,那么我完全沒有問題
cmd.Parameters.AddWithValue("@val", "This<7");
正如您在注釋行中所看到的,我已經嘗試匹配數據類型,但這不會引發任何錯誤並且不會更新表。 我也在其他專欄上對此進行了測試,並且有相同的基本問題。
所以我的問題是:在這種特殊情況下,應該使用哪段代碼來防止SQL插入?
這是使用使用動態sql的存儲過程的示例。 請注意,動態sql利用sp_executesql有助於防止sql注入攻擊。
SQL代碼
create PROCEDURE [dbo].[SP_DynamicUpdate]
-- Add the parameters for the stored procedure here
@col varchar(50) = null,
@val varchar(50) = null,
@id int = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
-- declaring strings
DECLARE @SQLString nvarchar(1024);
DECLARE @ParmDefinition nvarchar(512)
SET @SQLString =
N'Update
dbo.tb_Alumno
set
@col_Param = @val_Param
where
pk_alumno = @id_Param'
-- creating the parameters
SET @ParmDefinition = N'@col_Param varchar(50), ';
SET @ParmDefinition = @ParmDefinition + N'@val_Param varchar(50), ';
SET @ParmDefinition = @ParmDefinition + N'@id_Param int ';
-- Executing the stored procedure
EXECUTE sp_executesql @SQLString,
@ParmDefinition,
@col_Param = @col,
@val_Param = @val,
@id_Param = @id
END
C#代碼
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings[2].ConnectionString))
{
GridView gv = sender as GridView;
using (SqlCommand cmd = new SqlCommand("dbo.SP_DynamicUpdate", con))
{
#region Parameters
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@col", e.Column.FieldName);
cmd.Parameters.AddWithValue("@val", e.Value);
cmd.Parameters.AddWithValue("@id", gv.GetRowCellValue(gv.FocusedRowHandle, gv.Columns[0]));
#endregion
try
{
con.Open();
cmd.ExecuteNonQuery();
}
catch (Exception xe)
{
MessageBox.Show(xe.Message);
}
}
}
這將增加安全性,並允許您使用不同的參數分別測試存儲過程。 您甚至可以在存儲過程調用中添加更多檢查-就像存在對列名的檢查一樣。
就您執行SQL注入攻擊的方式而言,您沒有更多的選擇。
我能夠找到解決問題的最簡單方法,如下所示:
我沒有注意到,當我在datagrid和數據庫之間創建綁定時,會自動創建tableAdapter和dataSet。 通過此鏈接作為參考,我發現適配器具有更新方法,因此我使用了信息,因此我只使用了這段代碼,它像一個魅力一樣起作用,我還添加了一行以驗證該字段,說實話,我認為不是需要。
Validate(); //Or this.Validate();
tb_AlumnoTableAdapter.Update(escuelaDataSet.tb_Alumno);
和以前一樣,我將此代碼放在“ CellValueChanged”事件下,但我假設可以將其附加到按鈕上,以使其成為保存按鈕。 感謝大家的回答,希望對我這樣的人有所幫助。
您可能還想閱讀: 如何:使用TableAdapter更新數據 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.