在SQLite中管理多个写请求

时间:2013-07-10 17:17:50

标签: c# sqlite

我正在扩展现有的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();
            }
        }

1 个答案:

答案 0 :(得分: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. 它暴露在可能的竞争条件下,两个线程同时看到连接不忙,然后两个都尝试打开它。
  3. 使用互斥锁解决了这些问题。