1

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

1 回答 1

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. 它暴露在可能的竞争条件下,两个线程同时将连接视为不忙,然后都尝试打开它。

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

于 2013-07-10T17:32:26.530 回答