SQLite连接策略

时间:2013-02-08 15:04:08

标签: c# database sqlite nhibernate connection-string

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

  1. 当第一个用户以只读模式连接到它时(他没有 对该位置具有读写权限,或者对数据库具有读写权限 只读),其他用户也必须使用只读连接(甚至 如果他们有RW访问权限)。
  2. 当第一个用户在RW模式下连接到它时,其他用户不能 完全连接到数据库。
  3. 我正在使用SQLite,并发不应该是问题,因为数据库不应该同时超过10个人使用。

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

    更新:现在我终于明白了什么是@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;
        }
    
     }
    

    }

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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