2013-10-03 43 views
1

我面臨我的應用程序的問題。它是一個桌面應用程序,由c#和Sqlite DB進行緩存並且是多線程的。 我的問題是有時候緩存操作與其他線程的操作衝突。C#+ SQLite - 數據庫鎖

任何人都可以幫我解決還是如何解決是兩難境地?

我想解鎖數據庫(也許重新啓動程序),但我知道這不是一個好方法。

+0

我認爲你應該創建隊列與SQL命令並執行一個SQL的時間。您是否嘗試過使用/創建併發集合? – tray2002

+0

嗯如果我要爲sql命令創建一個隊列,這意味着即時消息將等待我命令被執行,以便我可以使用它的結果?看起來不是一個好的解決方案? – Fadz

+0

你是否得到數據庫鎖定(5)錯誤? – Max

回答

1

我想做同樣的事情,將SQLite數據庫鏈接到C#應用程序。我得到了:

Database is locked(5)

藏漢,我解決了這個在我的代碼使用Transactions,這裏是一個交易我用一個例子:

using (TransactionScope tran = new TransactionScope()) 
{ 
    //Perform action on SQLite Database here. 


    tran.Complete(); 
} 
+0

我已經在放置交易,這沒有問題。 我認爲問題的存在是因爲它的多線程,請參閱場景。線程1:插入項目列表。 線程2:正在刪除一些項目。 ,因爲表被線程1鎖定,同時線程2正在訪問它,然後它會導致問題。 (雖然我只是猜測這個,因爲我真的不知道處理器如何處理這種情況) – Fadz

+0

您是否使用事務處理所有操作到數據庫?這解決了我的問題。 – Max

+0

是啊..看起來像忘了使用回滾。不管怎麼說,還是要謝謝你。 – Fadz

5

SO Searcing類似的問題,共識似乎你需要自己鎖定。一些答案指出將相同的SqliteConnection對象傳遞給所有寫入的線程。雖然我認爲這不會解決問題。

我會建議重新考慮併發寫/讀。我假設你的線程做了一些工作,然後保存到該線程中的數據庫。我會重寫它,以便線程完成一些工作並返回輸出。將數據保存到db的過程不需要與執行工作的過程相結合。併發讀取應該沒有變化地工作,因爲鎖是一個用於讀取的shared。當然,可能會出現寫入和讀取同時發生的情況。在這種情況下,錯誤會再次彈出。

我認爲使用全局的lock object可能會更簡單,並使用它來同步/序列化所有的寫/讀操作。然而,當你這樣做的時候,你已經有效地使數據庫訪問單線程。這是其中一個問題,答案取決於你的最終目標是什麼。

順便說一句,你不應該使用數據庫級別的事務,而不是應用程序級別?像http://msdn.microsoft.com/en-us/library/86773566.aspx

using (SqlConnection connection = new SqlConnection(connectionString)) 
{ 
    connection.Open(); 

    SqlCommand command = connection.CreateCommand(); 
    SqlTransaction transaction; 

    // Start a local transaction. 
    transaction = connection.BeginTransaction("SampleTransaction"); 

    // Must assign both transaction object and connection 
    // to Command object for a pending local transaction 
    command.Connection = connection; 
    command.Transaction = transaction; 

    try 
    { 
     command.CommandText = 
      "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')"; 
     command.ExecuteNonQuery(); 
     command.CommandText = 
      "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')"; 
     command.ExecuteNonQuery(); 

     // Attempt to commit the transaction. 
     transaction.Commit(); 
     Console.WriteLine("Both records are written to database."); 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine("Commit Exception Type: {0}", ex.GetType()); 
     Console.WriteLine(" Message: {0}", ex.Message); 

     // Attempt to roll back the transaction. 
     try 
     { 
      transaction.Rollback(); 
     } 
     catch (Exception ex2) 
     { 
      // This catch block will handle any errors that may have occurred 
      // on the server that would cause the rollback to fail, such as 
      // a closed connection. 
      Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType()); 
      Console.WriteLine(" Message: {0}", ex2.Message); 
     } 
    } 
} 
+0

謝謝@Amith,它是我的不好,我有交易機制,開始和提交,但我忘記執行回滾後捕捉的豁免。感謝提醒。看起來現在表現很好。 – Fadz