【问题标题】:Sqlite database lockedSqlite 数据库被锁定
【发布时间】:2009-07-23 01:50:54
【问题描述】:

我正在使用 asp.net c# 并将 SqLite 数据库上传到服务器,然后进行一些插入和更新。问题是有时(我认为是更新出现问题时)数据库被锁定。所以下次我尝试再次上传文件时,它被锁定,我收到一条错误消息“该进程无法访问该文件,因为它正在被另一个进程使用”。如果事务期间出现问题,可能不会处理数据库文件?解决此问题的唯一方法是重新启动服务器。

如何在我的代码中解决它,这样即使出现问题,我也可以确保它始终处于解锁状态?

这是我的代码:

try
{
  string filepath = Server.MapPath("~/files/db.sql");

  //Gets the file and save it on the server
  ((HttpPostedFile)HttpContext.Current.Request.Files["sqlitedb"]).SaveAs(filepath);

  //Open the database
  SQLiteConnection conn = new SQLiteConnection("Data Source=" + filepath + ";Version=3;");

  conn.Open();
  SQLiteCommand cmd = new SQLiteCommand(conn);
  using (SQLiteTransaction transaction = conn.BeginTransaction())
  {
     using (cmd)
     {
        //Here I do some stuff to the database, update, insert etc
     }
     transaction.Commit();
  }
  conn.Close();
  cmd.Dispose();
}
catch (Exception exp)
{
//Error
}

【问题讨论】:

  • 线程以什么方式?不在我的asp.net代码中,在sqlite代码中我不确定,但我不这么认为?
  • asp.net 是多线程的,即使您没有明确创建它们。 asp.net 还能如何处理来自不同用户的请求?当您修改一个 sqlite 数据库时,整个数据库被锁定。您可以使用 sqlite 进行多线程读取,但写入(插入、更新、删除、创建表)会锁定整个数据库。我认为您必须使用 .net readerwriter-lock 类。

标签: c# asp.net sqlite locking


【解决方案1】:

您也可以尝试将 Connection 放在 using 块中,或在其上调用 Dispose:

//Open the database
using (SQLiteConnection conn = new SQLiteConnection("Data Source=" + filepath + ";Version=3;")) {
  conn.Open();
  using (SQLiteCommand cmd = new SQLiteCommand(conn)) {
    using (SQLiteTransaction transaction = conn.BeginTransaction()) {
      //Here I do some stuff to the database, update, insert etc
      transaction.Commit();
    }
  }
}

这将确保您正确处理连接对象(您目前没有,只是关闭它)。

将它们包装在 using 块中可确保即使发生异常也会调用 Dispose - 它实际上与编写相同:

// Create connection, command, etc objects.
SQLiteConnection conn;

try {
  conn = new SQLiteConnection("Data Source=" + filepath + ";Version=3;");
  // Do Stuff here...
}
catch (exception e) {
  // Although there are arguments to say don't catch generic exceptions,
  // but instead catch each explicit exception you can handle.
}
finally {
  // Check for null, and if not, close and dispose
  if (null != conn)
    conn.Dispose();
}

finally 块中的代码将被调用,无论异常如何,并帮助您清理。

【讨论】:

  • 谢谢!!如果我使用:“throw e;”在我的捕获中,finally 部分在抛出异常之前是否仍会运行?
【解决方案2】:

asp.net 应用程序在服务器中是多线程的。

您不能同时写入(插入、选择、更新...),因为整个数据库都被锁定了。没有写入时允许同时选择。

您应该使用 .NET ReaderWriterLock 类:http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlock.aspx

【讨论】:

    【解决方案3】:

    你不应该在conn.Close()之前做cmd.Dispose()吗?我不知道这是否有任何区别,但您通常希望按照与初始化顺序相反的顺序进行清理。

    【讨论】:

      【解决方案4】:

      简而言之,SQLite 处理非托管资源的方式与其他提供程序略有不同。您必须明确处置命令(即使您在 using() 块之外与阅读器一起工作,这似乎也有效。

      阅读此主题以获得更多风味: http://sqlite.phxsoftware.com/forums/p/909/4164.aspx

      【讨论】:

        猜你喜欢
        • 2011-10-30
        • 1970-01-01
        • 2011-08-05
        • 2015-05-11
        • 2011-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多