SQLite连接策略 [英] SQLite connection strategies

查看:192
本文介绍了SQLite连接策略的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a database that may be on the network drive. There are two things that I want to achieve:


  1. 当第一个用户以只读模式连接到它时不
    具有对该位置的读写访问权,或者数据库是
    只读),其他用户也必须使用只读连接(即使
    ,如果它们具有RW访问)。

  2. 当第一个用户在RW模式下连接到数据库时,其他人不能连接到数据库。

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

I'm using SQLite, and the concurrency should not be the problem, as the database should never be used by more than 10 people at the same time.

UPDATE:这是我想要进行工作的示例,所以我可以在程序中实现它。几乎一切都可以改变。

UPDATE: This is a sample that I'm trying to make work, so I could implement it in the program itself. Almost everything can be changed.

UPDATE:现在,当我终于明白了什么@CL。告诉我,我使它工作,这是更新的代码。

UPDATE: Now when I finally understood what @CL. was telling me, I made it work and this is the updated code.

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;
    }

 }

}

推荐答案

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

Set PRAGMA locking_mode=EXCLUSIVE to prevent SQLite from releasing its locks after a transaction ends.

这篇关于SQLite连接策略的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆