最近有些DataSet檔案裡面,需要修改TableAdapter裡面某些回傳單一值的Query,但修改完一跑,怎麼程式報錯?看看程式裡面,竟然回傳的型態變成Object了!!
如下圖,有個TableAdapter,除了預設的Fill方法外,還有兩個傳回單一值的query
以GetUserCount為範例,該sql應該會回傳一個int型態的資料
這個是Query剛建立好,在程式中的狀況,可看見提示是回傳int?,XSD原始碼內的ScalarCallRetval也顯示"System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",表示建立query之後可抓到正確的型態(為了方便截圖所以手動斷行)
接著對Query做修改,這裡其實什麼都沒改,就一直下一步直到按下完成
然後去看DataSet的xsd原始檔,竟然變成"System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",型態是Object了...@@
當然程式內如果相信第一次建立Query後的回傳型態,沒轉型,就會有錯…
TableAdapter裡面第二個GetUserName也是一樣,只是第一個是int第二個是string,只要修改過全都會變成Object
如果要解決,只能從修改程式下手,強迫在每個Query都指定資料型態才行!如下:
int? count = (int?)da.GetUserCount();
string name = (string)da.GetUserName(1);
好奇的是,既然第一次產生Query,按下完成後可以取得sql回傳的型態,為什麼再進去編輯,不會再從sql裡面再取得一次回傳的型態,就硬要把型態改為Object勒?不然也可以維持第一次的型態值不動啊!!@@
而在網路上搜尋的結果,這東西從Visual Studio 2005開始就一直存在相同的問題了,看來微軟只建議從程式面指定轉型下手,卻不認為第一次產生可抓到型態,第二次之後就強迫變成Object,這樣的方式是bug.....
--
更新
經朋友幫我轉寄給微軟工程師測試後,得到了回答,以下是往來內容:--
工程師:
這個問題不是 Bug,原因說明如後。
傳回單一值 (Single Value) 的 TableAdapter 查詢會根據查詢傳回資料型別(而不是傳回物件的 ExecuteScalar 方法),比方說,TableAdapter 查詢選取資料型別為整數 (integer) 的單一欄位(Single Column),則查詢的傳回值為整數。
單一純量 (Single Scalar) 查詢無法確知使用者會傳回什麼型別的資料,故需要對傳回值進行型 別轉換,如下圖是 MSDN 文件「如何:執行 TableAdapter 查詢」(網址:http://msdn.microsoft. com/zh-tw/library/ms233822. aspx),「執行可傳回單一 (純量) 值的 TableAdapter 查詢」一節的說明:
--
我:
可是第一次建立的時候可以取得型態呢! 只有在修改過後才會變成object, 如果第一次可以正確取得型態,為什麼第二次之後不行呢?
--
工程師:
如客戶先前 PDF 檔所述,使用 TableAdapter 組態精靈設定完畢之後,此時 .xsd 檔的 ScalarCallRetval型別 System.Int32 是正確的,但接著,再執行精靈進行設定(即便沒有改任何東西), 這時候,ScalarCallRetval 型別就改變為 System.Object。
原因是因為,於第一次啟用精靈進行設定時,精靈會連線到資料庫, 因此可以知道資料表之欄位型別,判斷出回傳的確實型別為何, 但第二次使用精靈,已經沒有再參照到原始的資料表欄位, 故會變成是存量 (Scalar) ,亦即被視為是 Object 型別的資料。
這部分的說明請參考「SqlCommand. ExecuteScalar 方法」(網址:來自 http://msdn.microsoft.com/zh- tw/library/system.data. sqlclient.sqlcommand. executescalar(v=vs.110).aspx), 如下圖所示傳回值的型別是 System.Object:
所以這個問題還是要靠自己勤勞點在程式碼轉型囉!!
沒有留言:
張貼留言