9

SQLite FAQから読み取ることができるので、いつでも複数のプロセスの読み取り(SELECT)と1つのプロセスの書き込み(INSERT、UPDATE、DELETE)データベースのみをサポートします。

SQLiteはリーダー/ライターロックを使用してデータベースへのアクセスを制御します。プロセスが書き込みを行う場合、更新中はデータベースファイル全体をロックする必要があります。しかし、それは通常、数ミリ秒しかかかりません。他のプロセスは、ライターが終了するのを待ってから、ビジネスを続行します

私はc#経由でSystem.Data.SQLiteアダプターを使用しています。

誰かが私にplzを説明してもらえますか、このプロセスはどの程度正確に行われていますか?

このプロセスは自動的に機能し、同じデータベース上ですでに実行されている別の書き込みSQLiteCommandがある場合、 SQLiteCommandの書き込みは単に待機しますか?

または多分それは例外をスローしますか?どんな感じ?

申し訳ありませんが、このメカニズムに関する情報は見つかりませんでした:)

ありがとうございました。

アップデート:

特定のエラーコードで例外が発生するという投稿を見つけました

その声明は正しいですか?

4

1 に答える 1

17

私はそれを自分で調べました:

(uniqueidentifier)と(nvarchar)の2つのフィールドを含むc:\123.db1つのテーブルを使用してサンプルSQLiteデータベースを作成しました。CategoriesIDName

次に、データベースへの複数の書き込みアクセスをエミュレートするマルチスレッドコードを作成しました(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!");
            }
        }
    }
}

私のCore2DuoE7500での結果は、例外が発生することはないということです。

SQLiteは私のニーズに合わせて十分に最適化されているようです(ロック/ロック解除は非常に高速で、SQLite FAQに記載されているように、通常は数ミリ秒しかかかりません)-すばらしい!

-の整数ErrorCodeを取得する必要はないことに注意してください。代わりにSQLiteException、特別な列挙型ReturnCodeフィールドを使用できます。すべてのコードはここで説明されています。

この情報が誰かに役立つことを願っています。

于 2013-03-14T06:33:26.293 に答える