2017-02-24 45 views
0

我想这样做:的SQLite一直这样做SELECT + UPDATE时锁定我的数据库(C#)

  1. 阅读从一个SQLite数据库行(在GetRuleByID()方法)
  2. 更新同一行我在刚才读(1)(见UpdateStatusForRuleID()方法)

但我的问题是,SQLite的在SELECT中GetRuleByID(后锁定数据库中),所以当所谓的在UpdateStatusForRuleID()的更新是唯一成功第一次。

我已经尝试启用SQLite以及PRAGMA read_uncommitted = 1日志记录以避免SQLite锁定数据库的SELECT,但这似乎不工作。

这应该很简单,但我到目前为止花了整整一个晚上试图解决这个问题...请帮助!

private static MicroRuleEngine.Rule GetRuleByID(int ruleID, SQLiteConnection connection, out Dictionary<string, string> dict) 
{ 
    dict = new Dictionary<string, string>(); 

    string sql = String.Format("select * from rules WHERE ID = {0} ", ruleID.ToString()); 
    SQLiteCommand command = new SQLiteCommand(sql, connection); 
    SQLiteDataReader reader = command.ExecuteReader(); 

    if (reader.HasRows) 
    { 
     reader.Read(); 

     // Convert row into a dictionary 
     for (int lp = 0; lp < reader.FieldCount; lp++) 
     { 
      dict.Add(reader.GetName(lp), reader.GetValue(lp) as string); 
     } 

     string json = dict["fulljson"]; 
     MicroRuleEngine.Rule r = Newtonsoft.Json.JsonConvert.DeserializeObject<MicroRuleEngine.Rule>(json); 

     //command.Dispose();    

     return r; 
    } 

}

internal static void UpdateStatusForRuleID(SQLConnectionManager DBMANAGER, int ruleID, bool status) 
{ 
    Dictionary<string, string> dict = null; 

    string dbVal = (status) ? "1" : "0"; 
    MicroRuleEngine.Rule r = null; 
    string newJSON = null; 

    using (SQLiteConnection connection = DBMANAGER.CreateConnection()) 
    { 
     r = GetRuleByID(ruleID, connection, out dict); 
     r.Active = (status); 
     newJSON = Newtonsoft.Json.JsonConvert.SerializeObject(r); 

     Thread.Sleep(1000); 

     string sql = "UPDATE rules SET active = @a, [email protected] WHERE ID = @i"; 

     using (var command = new SQLiteCommand(sql, connection)) 
     { 
      command.Parameters.Add(new SQLiteParameter("@a", dbVal)); 
      command.Parameters.Add(new SQLiteParameter("@i", ruleID)); 
      command.Parameters.Add(new SQLiteParameter("@j", newJSON)); 

      command.ExecuteNonQuery(); // Database is locked here ??? 
     } 

     connection.Close(); 
    } 

}

+1

1.从上面的代码我没有看到两种方法之间的关系2.你是什么意思的'锁',以及如何确定是否锁定? –

+0

第一部分为命令对象创建一个using块。在第二部分中,connection.Close();可以留下,因为你实现了use-block和.Close();内部只需调用.Dispose();这是由你的使用块完成的。进一步说,你有什么理由使用Thread.Sleep(1000); ??? – Sebi

+0

那么调用代码调用UpdateStatusForRuleID(),然后在执行实际的UPDATE命令之前调用GetRuleByID()。 –

回答

0

“数据库被锁定” 指的是一些其它连接(在相同的或其他一些方法)仍然具有活性的事务。

你不需要多个连接(除非你使用多个线程)。只需使用单个连接对象进行所有数据库访问。

确保所有命令,读卡器和交易对象(连接,如果你决定使用暂时的)被正确地清理,通过使用using

using (var command = new SQLiteCommand(sql, connection)) 
using (var reader = command.ExecuteReader()) 
{ 
    if (reader.HasRows) 
    ... 
} 
0

显然,下面的作品的代码。我基本上删除了GetRuleByID()方法(但后来我不得不重写其他4种方法)

感谢所有提供了输入的人。

 internal static void UpdateStatusForRuleID(SQLConnectionManager DBMANAGER, int ruleID, bool status) 
    { 
     string dbVal = (status) ? "1" : "0"; 
     MicroRuleEngine.Rule r = null; 
     string newJSON = null; 

     using (SQLiteConnection conn = DBMANAGER.CreateConnection()) 
     { 
      string sql = String.Format("select * from rules WHERE ID = {0} ", ruleID.ToString()); 

      using (var command = new SQLiteCommand(sql, conn)) 
      using (var reader = command.ExecuteReader()) 
      { 
       if (reader.HasRows) 
       { 
        reader.Read(); 

        string json = reader["fulljson"].ToString(); 
        r = Newtonsoft.Json.JsonConvert.DeserializeObject<MicroRuleEngine.Rule>(json); 
        r.Active = (status); 
        newJSON = Newtonsoft.Json.JsonConvert.SerializeObject(r); 

        string sql2 = "UPDATE rules SET active = @a, [email protected] WHERE ID = @i"; 

        using (var command2 = new SQLiteCommand(sql2, conn)) 
        { 
         command2.Parameters.Add(new SQLiteParameter("@a", dbVal)); 
         command2.Parameters.Add(new SQLiteParameter("@i", ruleID)); 
         command2.Parameters.Add(new SQLiteParameter("@j", newJSON)); 

         command2.ExecuteNonQuery(); 
        } 
       } 
      } 
     } 
    }