【问题标题】:Managing multiple write request in SQLite在 SQLite 中管理多个写入请求
【发布时间】:2013-07-10 17:17:50
【问题描述】:

我正在扩展一个现有的 C# 应用程序,该应用程序使用 SQLite 数据库以在 LAN 上使用。最多 1-4 台 PC 将同时使用它。我不是一个非常有经验的程序员,因此需要一些专家建议来处理多个write 对数据库的请求。我知道 SQLite 不是为客户端/服务器应用程序而设计的。但是我的应用程序没有大量的数据库使用。我要注意所有查询都得到正确处理。当 SQLite 尝试访问被另一个进程锁定的文件时,默认行为是返回 SQLITE_BUSY。

在我的代码中,我正在检查连接是否忙,然后我正在运行一个 while 循环以等待一段时间,然后递归调用 openConnection() 方法,直到连接状态从忙更改。

这是正确的方法吗?

public bool OpenConnection()
{
   if (Con == null)
   {
      Con = new SQLiteConnection(ConnectionString);
   }

   if ((Con.State != ConnectionState.Open)&&(Con.State==ConnectionState.Broken || Con.State==ConnectionState.Closed))
   {
      Con.Open();

      Cmd = new SQLiteCommand("PRAGMA FOREIGN_KEYS=ON", Con);
      Cmd.ExecuteNonQuery();
      Tr = Con.BeginTransaction(IsolationLevel.ReadCommitted);
      return true;
   }

   if(IsConnectionBusy())
   {
      int count = 10000;
      while (count!=0)
      {
         count--;
      }
      OpenConnection();
   }
   return false;
}

public bool IsConnectionBusy()
{
   switch (Con.State)
   {
      case ConnectionState.Connecting:
      case ConnectionState.Executing:
      case ConnectionState.Fetching:
      return true;
   }
   return false;
}

 public Boolean CloseConnection()
        {
            if (Con != null && Con.State == ConnectionState.Open)
            {
                Tx.Commit();
                Con.Close();
                return true;
            }
            return false;
        }




public Boolean ExecuteNonQuery(string sql)
        {
            if (sql == null) return false;
            try
            {
                if (!OpenConnection())
                    return false;
                else
                {
                    Cmd = new SQLiteCommand(sql, Con){Transaction = Tx};
                    Cmd.ExecuteNonQuery();
                    return true;
                }
            }
            catch (Exception exception)
            {
                Tx.Rollback();
                Msg.Log(exception);
                return false;
            }
            finally
            {
                CloseConnection();
                Cmd.Dispose();
            }
        }

【问题讨论】:

    标签: c# sqlite


    【解决方案1】:

    通常您可以使用锁(互斥锁)来管理对共享资源的访问。一次只能有一个线程持有锁。

    例如:

    public class ConnectionClass
    {
        private static object lockobj = new object();
    
        public Result ExecuteQuery(Query query)
        {
            // wait until the resource is available
            lock (lockobj)
            {
                // open connection, get results
            }
        }
    }
    

    OP 中的轮询方法存在两个潜在问题:

    1. 通过轮询,您可能会导致客户端的等待时间超出必要时间。
    2. 它暴露在可能的竞争条件下,两个线程同时将连接视为不忙,然后都尝试打开它。

    使用互斥锁可以解决这些问题。

    【讨论】:

    • 感谢您指出我的代码中存在竞争条件的可能性。
    • 我会按照你的建议使用锁。谢谢。 :-)
    • @McGarnagle 有没有可能同一个线程在锁被释放后可以调用写函数,但数据库文件的锁仍然没有被释放。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多