2011-06-15 120 views
3

我正在使用下面的方法獲取最後插入的行的ID。獲取最後一個插入的ID

Database.ExecuteNonQuery(query, parameters); 

    //if another client/connection inserts a record at this time, 
    //could the line below return the incorrect row ID? 
    int fileid = Convert.ToInt32(Database.Scalar("SELECT last_insert_rowid()")); 
    return fileid; 

這種方法到目前爲止工作得很好,但我不確定它是否完全可靠。

假設有兩個客戶端應用程序,每個客戶端應用程序都有自己單獨的數據庫連接,它們完全同時調用上面的服務器端方法。請記住,客戶端線程並行運行,並且SQLite一次只能運行一個操作(或者我聽說過),一個客戶端實例是否可以返回插入的記錄的行ID另一個例子?

最後,有沒有更好的方法來獲取最後插入的行ID?

回答

6

如果另一個客戶端/連接此時插入一條記錄,下面的行是否可以返回不正確的行ID?

不,因爲寫入要麼發生在讀取之後,要麼發生在讀取之後,而是發生在讀取之前,而不發生在讀取期間。

請記住,客戶端線程並行運行,並且SQLite一次只能運行一個操作,一個客戶端是否可以獲取由另一個客戶端插入的記錄的行ID ?

是的,當然。

服務器端方法在同一時間調用並不重要。數據庫的鎖定允許併發讀取,但不能併發寫入,或寫入時讀取。

如果你還沒有,請閱讀SQLite's file locking model

+1

在代碼中評論的問題與問題的其餘部分一樣要求相同的問題。註釋行僅用於標記我認爲另一個客戶端實例可以插入記錄的時間。 – rafale 2011-06-15 05:33:48

+0

好的。儘管如此,我們很清楚,註釋行並不表示比「SELECT」之前更具體的時間。 – 2011-06-15 05:36:50

+0

是的,「在SELECT之前」是我的意思。我只是不確定你爲什麼一開始不回答。在讀取期間寫入不會發生,但是在讀取另一個客戶端之前可能發生來自一個客戶端的寫入。該客戶端然後將獲得由另一個客戶端插入的行的ID。理想情況下,我會讓SQLite在INSERT之後執行鎖定,然後在SELECT之後釋放。 – rafale 2011-06-15 05:45:50

2

如果insert命令和get last inserted row id命令都在同一個寫入鎖中,並且在這兩個命令之間沒有其他插入命令可以在這兩個命令之間運行,那麼您就很安全。

如果您在insert命令之後啓動寫入鎖定,則無法確定另一個線程是否先沒有寫入鎖定。如果另一個線程先得到一個寫鎖,那麼在其他線程釋放它們的鎖之前,您將無法執行對該行ID的搜索。屆時,如果另一個線程插入一個新行就可能爲時已晚。