簡體   English   中英

通過System.Data.SQLite和c#多次訪問單個SQLite數據庫文件

[英]Multiple access to a single SQLite database file via System.Data.SQLite and c#

正如我可以從SQLite FAQ中讀到的,它支持多個進程讀取(SELECT),並且在任何時刻都只支持一個進程寫入(INSERT,UPDATE,DELETE)數據庫:

SQLite使用讀取器/寫入器鎖來控制對數據庫的訪問。 當任何進程想要寫入時,它必須在更新期間鎖定整個數據庫文件。 但這通常只需要幾毫秒。 其他流程只是等待作者完成然后繼續他們的業務

我通過c#使用System.Data.SQLite適配器。

有人可以告訴我PLZ,這個過程到底是怎么回事?

這個過程是否會自動運行,編寫SQLiteCommand只會等待另一個SQLiteCommand已經在同一個數據庫上執行?

或者它可能會拋出異常? 什么樣的?

抱歉,但我沒有找到有關此機制的信息:)

謝謝。

更新:

我發現帖子說異常會引發一個特定的錯誤代碼

這句話是否正確?

我自己調查了一下:

我創建了一個示例SQLite數據庫c:\\123.db ,其中包含一個表包含兩個字段的CategoriesID (uniqueidentifier)和Name (nvarchar)。

然后我編寫了一些多線程代碼來模擬對數據庫的多次寫訪問(如果使用此代碼,請不要忘記向項目添加System.Data.SQLite引用):

using System;
using System.Data.SQLite;
using System.Threading.Tasks;

namespace SQLiteTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var tasks = new Task[100];

            for (int i = 0; i < 100; i++)
            {
                tasks[i] = new Task(new Program().WriteToDB);
                tasks[i].Start();
            }

            foreach (var task in tasks)
                task.Wait();
        }

        public void WriteToDB()
        {
            try
            {
                using (SQLiteConnection myconnection = new SQLiteConnection(@"Data Source=c:\123.db"))
                {
                    myconnection.Open();
                    using (SQLiteTransaction mytransaction = myconnection.BeginTransaction())
                    {
                        using (SQLiteCommand mycommand = new SQLiteCommand(myconnection))
                        {
                            Guid id = Guid.NewGuid();

                            mycommand.CommandText = "INSERT INTO Categories(ID, Name) VALUES ('" + id.ToString() + "', '111')";
                            mycommand.ExecuteNonQuery();

                            mycommand.CommandText = "UPDATE Categories SET Name='222' WHERE ID='" + id.ToString() + "'";
                            mycommand.ExecuteNonQuery();

                            mycommand.CommandText = "DELETE FROM Categories WHERE ID='" + id.ToString() + "'";
                            mycommand.ExecuteNonQuery();
                        }
                        mytransaction.Commit();
                    }
                }
            }
            catch (SQLiteException ex)
            {
                if (ex.ReturnCode == SQLiteErrorCode.Busy)
                    Console.WriteLine("Database is locked by another process!");
            }
        }
    }
}

我的Core2Duo E7500的結果是永遠不會出現異常!

看起來SQLite已根據我的需求進行了優化(鎖定/解鎖非常快,通常只需幾毫秒,如SQLite FAQ告訴我們的那樣) - 太棒了!

請注意,不需要為SQLiteException檢索整數ErrorCode - 您可以使用特殊的枚舉ReturnCode字段。 這里描述所有代碼。

希望這些信息對某人有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM