環境: ADO.NET
執行ADO.NET 的 ExecuteNoQuery ,結果發生了「參數化查詢 ... 必須有參數 ...,但未提供。」的錯誤。
明明就有給 SqlParameter 呀! 為何產生這個錯誤呢?
測試的SQL如下,
CREATE TABLE t1 (
id INT PRIMARY KEY IDENTITY(1, 1),
c1 VARCHAR(10)
)
GO
上面 t1 這個資料表 c1 欄位是允許輸入 null 的,所以值給 null 或是 default 的話,是可以順利將 null 值 insert 進去的,如下,
insert into t1(c1) values(null);
insert into t1(c1) values(DEFAULT);
測試的程式碼如下,
private static void ADOInsertExecuteSQLDemo()
{
string connstring = "db連線字串";
string c1 = null;
using (var conn = new SqlConnection(connstring))
{
conn.Open();
var comm = new SqlCommand("insert into t1(c1) values(@c1);");
comm.Connection = conn;
comm.Parameters.AddWithValue("@c1", c1);
comm.ExecuteNonQuery();
}
}
因為使用 ADO.NET 參數執行 SQL,它會透過 sp_executesql 去執行,SQL如下,
exec sp_executesql N'insert into t1(c1) values(@c1);',N'@c1 nvarchar(4000)',@c1=default
因為參數@c1會被設定成 DEFAULT ,所以就出現那個錯誤,如下,
當然,如果在宣告 @c1 變數時有給變數值的話,就不會有問題,如下,
筆者本來想嘗試看看能不能從 SqlParameter 來設定讓參數有預設值,但沒有找到。
所以程式中只能判斷參數值是否為 null ,如果是 null 的話,就要轉成 DBNull.Value ,如下,
string connstring = "db連線字串";
string c1 = null;
using (var conn = new SqlConnection(connstring))
{
conn.Open();
var comm = new SqlCommand("insert into t1(c1) values(@c1);");
comm.Connection = conn;
comm.Parameters.AddWithValue("@c1", (object)c1 ?? DBNull.Value);
comm.ExecuteNonQuery();
}
轉成SQL, 參數@c1就會被設定成 null , 如下,
如果用 Entity Framework 就方便多了,因為它會幫我們 handle , 而且程式碼也簡單多了! 程式及SQL如下,
using (var db = new EFEntities())
{
var tb1 = new t1() { c1 = null };
db.t1.Add(tb1);
db.SaveChanges();
}
參考資料
Creating null value SqlParameter parameter objects with AddWithValue
Hi,
亂馬客Blog已移到了 「亂馬客 : Re:從零開始的軟體開發生活」
請大家繼續支持 ^_^