2013-03-06 49 views
0

我是F#的新手,試着先潛水,然後再做更正式的介紹。我有以下代碼:如何使用F#中的IDataReader字符串索引?

​​3210

我計劃yield語句來代替循環體和清理的代碼。但現在我只是試圖通過調試代碼和查看數據讀取器來確保數據訪問的工作。目前我收到System.InvalidCastException。當我把一個斷點通過上面的註釋行指示的點,然後在不久的窗戶reader["name"]型我從數據庫中獲取一個有效的值,所以我知道它連接到數據庫確定。但是,如果我嘗試將reader["name"](而不是reader.["name"])放在源文件中,我會得到「此值不是函數並且無法應用」消息。

爲什麼我可以在即時窗口使用reader["name"],但不能在我的fsharp代碼中使用?我如何在閱讀器上使用string indexing

更新

繼傑克P.的意見,我打出了代碼分成幾行,現在我看到那裏發生的錯誤:

let id = reader.["id"] 
    let id_unboxed = unbox id // <--- error on this line 

id有根據的類型object {long}調試器。

回答

3

您可以在立即窗口中使用reader["name"],因爲立即窗口使用C#語法而不是F#語法。

有一點需要注意:由於F#比C#更簡潔,因此可以在單行內進行很多操作。換句話說,在線上設置斷點可能無助於縮小問題範圍。在這些情況下,我通常會將表達式「擴展」爲多行上的多個let-binding;這樣做可以更容易地逐步通過表達和發現問題(在這一點,你可以做出改變你原有的單行)的原因。

如果您將項目訪問和unbox調用到他們自己的let-bindings中,會發生什麼?例如:

while reader.Read() do 
    let y = 0 
    // breakpoint here 
    let id = reader.["id"] 
    let id_unboxed : int = unbox id 
    let name = reader.["name"] 
    let name_unboxed : string = unbox name 
    x <- { Id = id_unboxed; Name = name_unboxed; } 
x 
+0

這很有幫助。 'let id_unboxed = unbox id'這一行有錯誤。在調試器中查看'id'的類型,它顯示'object {long}'。在直接窗口中,'id is long'返回true,而'id is int'則返回false。所以我猜測它與int vs long casting有關。將進一步試驗。 – User 2013-03-06 21:39:38

+1

@User如果它是'long',那麼你需要將它作爲'int64'(F#語法用於'long')。我認爲你需要將它解包到正確的類型('int64')*然後*將它轉換爲一個'int'(如果這是你所需要的) - 你不能直接解開它(這會導致錯誤,現在重新看到)。 – 2013-03-06 22:04:28

+0

如果我改變我的人類類型使用'int64'而不是'int'它的作品。不知道爲什麼它只是從數據庫拉ID。 – User 2013-03-06 22:10:36

4

傑克已經回答了有關不同的語法在F#和即時窗口或手錶索引的問題,所以我會跳過。

根據我的經驗,在從數據庫讀取數據時獲取System.InvalidCastException的最常見原因是由reader.["xyz"]返回的值實際上是DbNull.Value而不是實際的字符串或整數。鑄造DbNull.Value爲整數或字符串會失敗(因爲它是一個特殊值),所以如果你用空列的工作,你需要明確檢查:通過定義

let name = reader.["name"] 
let name_unboxed : string = 
    if name = DbNull.Value then null else unbox name 

可以使代碼更好?運營商允許你寫reader?name進行查找。如果你正在處理空值,你也可以使用reader?name defaultValue,定義如下:

let (?) (reader:IDataReader) (name:string) (def:'R) : 'R = 
    let v = reader.[name] 
    if Object.Equals(v, DBNull.Value) then def 
    else unbox v 

的代碼就變成了:

let name = reader?name null 
let id = reader?id -1 

這也應該簡化調試,你可以進入的?實施並看看發生了什麼。

相關問題