ADO.NET的SqlParameter(String,?Object)的構造函數第二個參數不能為0?
上述截圖的Line 22能正確執行,而Line 27卻拋異常(System.Data.SqlClient.SqlException). 查了一下MSDN (SqlParameter Constructor (String, Object) (System.Data.SqlClient)),裡面提到第二個參數需要把整數轉換成Object類型。現在有兩個疑問,1:為什麼需要把Integer轉成Object類型?我查看了一下SqlParameter的所有重載構造函數, 第二個參數直接傳整數不會有衝突啊? 2:如果是有其它原因導致了第二個參數需要把整數轉換成Object類型, 那為什麼截圖裡的Line 22能正確執行呢?Line 22和Line 27兩種使用方式有區別嗎?
補充一下代碼文字版:
SqlConnection connection = new SqlConnection("sql connection string");
SqlCommand command = connection.CreateCommand();
command.CommandText = "select * from INFORMATION_SCHEMA.COLUMNS where ORDINAL_POSITION &> @para" ;
int value = 0;
command.Parameters.Add(new SqlParameter("para", value));
SqlDataAdapter adapter = new SqlDataAdapter(command);
DataTable table = new DataTable();
adapter.Fill(table);adapter = new SqlDataAdapter(command);
command.Parameters.Clear();
command.Parameters.Add(new SqlParameter("para", 0)); //而這麼寫就可以了 command.Parameters.Add(new SqlParameter("para", (object)0))
adapter.Fill(table);
項目的版本是 .Net Framework 4.5.2, IDE是VS 2015.
Line 27的異常信息是:The parameterized query "(@para bigint)select * from INFORMATION_SCHEMA.COLUMNS where ORD" expects the parameter "@para", which was not supplied.
@Ivony 提到說不要復用 SqlCommand 對象,我給分割成了兩個方法,還是會有同樣的錯誤,代碼源碼和運行截圖如下(更新後的截圖):
確定了,這是一個規範中定義的行為,先引用規範:
6.1.3 隱式枚舉轉換
隱式枚舉轉換允許將 decimal-integer-literal 0(或 0L 等)轉換為任何 enum-type 以及任何基礎類型為 enum-type 的 nullable-type。在後一種情況下,此轉換通過轉換為基礎 enum-type 並包裝結果(第 4.1.10 節)來計算。
也就是說,0這個特殊的數值字面量(不論其是什麼類型),有一個到任意枚舉類型的隱式類型轉換。
這個隱式類型轉換有兩個前提條件:
1、必須是0
2、必須是字面量。你的例子正好符合這兩個條件,所以這個0d存在一個到SqlDbType這個枚舉的隱式類型轉換。因為其存在到SqlDbType和object兩個類型的隱式類型轉換,按照重載決策,SqlDbType是「更好的類型」,所以選擇SqlDbType的這個重載。
當你把這個0值放在一個變數傳進去的時候,則不符合上面的第二個前提條件,必須是字面量,所以此時不存在到SqlDbType的隱式類型轉換,所以這個時候選擇object的這個重載。你把sql寫在程序里,那麼發生這種事情就不意外了。
正確的做法是,sql應該寫在資料庫存儲過程里,然後EF直接調用。推薦閱讀:
※處理XMLHttpRequest時如何判斷是否是自己網站發出的?
※.net怎麼實現自己的非同步方法?
※請各位前輩指導下簡練代碼的思路?
※IoC/AOP 這些開發範式為什麼在 .NET 平台上沒有被廣泛採用?
※C# 是使用引用計數來發現垃圾對象的嗎?
TAG:NET | C# | MicrosoftSQLServer |