SQLite连接策略

本文关键字:策略 连接 SQLite | 更新日期: 2023-09-27 17:58:26

我有一个数据库,可能在网络驱动器上。我想实现两件事:

  1. 当第一个用户以只读模式连接到它时(他没有对该位置具有读写访问权限,或者数据库只读),其他用户也必须使用只读连接(甚至如果它们具有RW访问)
  2. 当第一个用户以RW模式连接到它时,其他用户不能完全连接到数据库

我使用的是SQLite,并发性应该不是问题,因为数据库不应该同时被超过10个人使用。

UPDATE:这是一个我正在尝试使其工作的示例,因此我可以在程序本身中实现它。几乎所有的事情都可以改变。

更新:现在我终于明白了什么@CL。告诉我,我做到了,这是更新的代码。

using System.Diagnostics;
using System.Linq;
using System.IO;
using DbSample.Domain;
using DbSample.Infrastructure;
using NHibernate.Linq;
using NHibernate.Util;

namespace DbSample.Console
{
    class Program
    {
        static void Main(string[] args)
        {
            IDatabaseContext databaseContext = null;
            databaseContext = new SqliteDatabaseContext(args[1]);
        var connection = LockDB(args[1]);
        if (connection == null) return;
        var sessionFactory = databaseContext.CreateSessionFactory();
        if (sessionFactory != null)
        {
            int insertCount = 0;
            while (true) 
            {
                try
                {
                    using (var session = sessionFactory.OpenSession(connection))
                    {
                        string result;
                        session.FlushMode = NHibernate.FlushMode.Never;
                        var command = session.Connection.CreateCommand();
                        command.CommandText = "PRAGMA locking_mode=EXCLUSIVE";
                        command.ExecuteNonQuery();

                        using (var transaction = session.BeginTransaction(ReadCommited))
                        {
                            bool update = false;
                            bool delete = false;
                            bool read = false;
                            bool readall = false;
                            int op = 0;
                            System.Console.Write("'nMenu of the day:'n1: update'n2: delete'n3: read'n4: read all'n0: EXIT'n'nYour choice: ");
                            op = System.Convert.ToInt32(System.Console.ReadLine());
                            if (op == 1)
                                update = true;
                            else if (op == 2)
                                delete = true;
                            else if (op == 3)
                                read = true;
                            else if (op == 4)
                                readall = true;
                            else if (op == 0)
                                break;
                            else System.Console.WriteLine("Are you retarded? Can't you read?");


                            if (delete)
                            {
                                System.Console.Write("Enter the ID of the object to delete: ");
                                var objectToRemove = session.Get<MyObject>(System.Convert.ToInt32(System.Console.ReadLine()));
                                if (!(objectToRemove == null))
                                {
                                    session.Delete(objectToRemove);
                                    System.Console.WriteLine("Deleted {0}, ID: {1}", objectToRemove.MyName, objectToRemove.Id);
                                    deleteCount++;
                                }
                                else
                                    System.Console.WriteLine("'nObject not present in the database!'n");

                            }
                            else if (update)
                            {
                                System.Console.Write("How many objects to add/update? ");
                                int number = System.Convert.ToInt32(System.Console.ReadLine());
                                number += insertCount;
                                for (; insertCount < number; insertCount++)
                                {
                                    var myObject = session.Get<MyObject>(insertCount + 1);
                                    if (myObject == null)
                                    {
                                        myObject = new MyObject
                                            {
                                                MtName = "Object" + insertCount,
                                                IdLegacy = 0,
                                                                                           };
                                        session.Save(myObject);
                                        System.Console.WriteLine("Added {0}, ID: {1}", myObject.MyName, myObject.Id);
                                    }
                                    else
                                    {
                                        session.Update(myObject);
                                        System.Console.WriteLine("Updated {0}, ID: {1}", myObject.MyName, myObject.Id);
                                    }
                                }
                            }
                            else if (read)
                            {
                                System.Console.Write("Enter the ID of the object to read: ");
                                var objectToRead = session.Get<MyObject>(System.Convert.ToInt32(System.Console.ReadLine()));
                                if (!(objectToRead == null))
                                    System.Console.WriteLine("Got {0}, ID: {1}", objectToRead.MyName, objectToRead.Id);
                                else
                                    System.Console.WriteLine("'nObject not present in the database!'n");
                            }
                            else if (readall)
                            {
                                System.Console.Write("How many objects to read? ");
                                int number = System.Convert.ToInt32(System.Console.ReadLine());
                                for (int i = 0; i < number; i++)
                                {
                                    var objectToRead = session.Get<MyObject>(i + 1);
                                    if (!(objectToRead == null))
                                        System.Console.WriteLine("Got {0}, ID: {1}", objectToRead.MyName, objectToRead.Id);
                                    else
                                        System.Console.WriteLine("'nObject not present in the database! ID: {0}'n", i + 1);

                                }
                            }
                            update = false;
                            delete = false;
                            read = false;
                            readall = false;
                            transaction.Commit();
                        }
                    }    
                }
                catch (System.Exception e)
                {
                    throw e;
                }

            }
            sessionFactory.Close();
        }
    }
    private static SQLiteConnection LockDbNew(string database)
    {
        var fi = new FileInfo(database);
        if (!fi.Exists)
            return null;
        var builder = new SQLiteConnectionStringBuilder { DefaultTimeout = 1, DataSource = fi.FullName, Version = 3 };
        var connectionStr = builder.ToString();
        var connection = new SQLiteConnection(connectionStr) { DefaultTimeout = 1 };
        var cmd = new SQLiteCommand(connection);
        connection.Open();
        // try to get an exclusive lock on the database
        try
        {
            cmd.CommandText = "PRAGMA locking_mode = EXCLUSIVE; BEGIN EXCLUSIVE; COMMIT;";
            cmd.ExecuteNonQuery();
        }
        // if we can't get the exclusive lock, it could mean 3 things
        // 1: someone else has locked the database
        // 2: we don't have a write acces to the database location
        // 3: database itself is a read-only file
        // So, we try to connect as read-only
        catch (Exception)
        {
            // we try to set the SHARED lock
            try
            {
                // first we clear the locks
                cmd.CommandText = "PRAGMA locking_mode = NORMAL";
                cmd.ExecuteNonQuery();
                cmd.CommandText = "SELECT COUNT(*) FROM MyObject";
                cmd.ExecuteNonQuery();
                // then set the SHARED lock on the database
                cmd.CommandText = "PRAGMA locking_mode = EXCLUSIVE";
                cmd.ExecuteNonQuery();
                cmd.CommandText = "SELECT COUNT(*) FROM MyObject";
                cmd.ExecuteNonQuery();
                readOnly = true;
            }
            catch (Exception)
            {
                // if we can't set EXCLUSIVE nor SHARED lock, someone else has opened the DB in read-write mode and we can't connect at all
                connection.Close();
                return null;
            }
        } 
        return connection;
    }
 }

}

SQLite连接策略

设置PRAGMA locking_mode=EXCLUSIVE以防止SQLite在事务结束后释放其锁。

我不知道这是否可以在数据库中完成,但可以在应用程序中完成;你可以设置一个全局变量(不确定是网络应用程序还是桌面应用程序)来检查是否有人连接,并且他是否有写访问权限。之后,您可以检查其他客户端的状态。