[ADO.NET]參數化查詢 ... 必須有參數 ...,但未提供。

環境: 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:從零開始的軟體開發生活

請大家繼續支持 ^_^