SQLite: '无法打开数据库文件'包含多个命令的事务例外

本文关键字:命令 事务 包含多 数据库 SQLite 文件 | 更新日期: 2023-09-27 18:02:19

我有以下(简化)代码:

IDbConnection connection = new SQLiteConnection(GetConnectionString());
if (connection.State == ConnectionState.Closed)
  connection.Open();
using (IDbTransaction transaction = connection.BeginTransaction())
{
  using (IDbCommand cmd = transaction.Connection.CreateCommand())
  {
    cmd.CommandText = "DELETE FROM Records2 WHERE ClientIndex = @ClientIndex";
    AddParameter(cmd, "@ClientIndex", DbType.Int32, clientIndex);
    cmd.ExecuteNonQuery();
  }
  using (IDbCommand cmd = transaction.Connection.CreateCommand())
  {
    cmd.CommandText = "INSERT INTO Records2(ClientIndex, CandidateIndex, Name)";
    cmd.CommandText += " VALUES(@ClientIndex, @CandidateIndex, @Name)";
    AddParameter(cmd, "@ClientIndex", DbType.Int32, clientIndex);
    IDbDataParameter pIndex = AddParameter(cmd, "@CandidateIndex", DbType.Int32, null);
    IDbDataParameter pName = AddParameter(cmd, "@Name", DbType.AnsiString, null);
    int index = 0;
    foreach (Record record in records)
    {
      pIndex.Value = index++;
      pName.Value = record.Name;
      cmd.ExecuteNonQuery();
    }
  }
  using (IDbCommand cmd = transaction.Connection.CreateCommand())
  {
    cmd.CommandText = "UPDATE Records SET Status = @Status, UpdateDate = @UpdateDate WHERE ClientIndex = @ClientIndex";
    AddParameter(cmd, "@ClientIndex", DbType.Int32, clientIndex);
    AddParameter(cmd, "@Status", DbType.Byte, status);
    AddParameter(cmd, "@UpdateDate", DbType.DateTime, DateTime.Now);
    cmd.ExecuteNonQuery();
  }
  transaction.Commit();
}
connection.Close();

:

private IDbDataParameter AddParameter(IDbCommand command, string paramName, DbType type, object value)
{
  IDbDataParameter parameter = command.CreateParameter();
  parameter.ParameterName = paramName;
  parameter.DbType = type;
  if (value != null)
    parameter.Value = value;
  else
    parameter.Value = DBNull.Value;
  command.Parameters.Add(parameter);
  return parameter;
}

所有的ExecuteNonQueries都可以正常工作,除了最后一个。在我的机器(运行xp)上,我得到以下异常,但在其他机器(运行windows 7)上,它可以正常工作,具有相同的代码和相同的数据库文件。

SQLiteException (0x80004005): Unable to open the database file
  System.Data.SQLite.SQLite3.Reset(SQLiteStatement stmt) +375
  System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt) +199
  System.Data.SQLite.SQLiteDataReader.NextResult() +226
  System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave) +87
  System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior) +38
  System.Data.SQLite.SQLiteCommand.ExecuteNonQuery() +39

我尝试在连接字符串中使用JournalMode = Perist,并且我从杀毒软件中排除了包含数据库文件的目录,但没有任何帮助。

我使用的是3.5框架,我的System.Data.SQLite版本是1.0.66.0。

有什么想法吗?

提前感谢,

Marc

SQLite: '无法打开数据库文件'包含多个命令的事务例外

我在1.0.87和1.0.89中遇到了同样的问题,最终(在procmon的帮助下)找到了原因。这实际上是一个误导性的错误信息,因为它不是数据库文件本身被拒绝访问,而是SQLite语句日志。

虽然在正确的位置创建了SQLite数据库文件和日志,并且该文件夹的权限允许访问Everyone,但SQLite仍然使用%TEMP%作为其语句日志。%TEMP%映射到运行服务的身份的用户配置文件下的临时文件夹。因此,当一个非特权客户端身份访问服务(并在服务内部和背后进行模拟)时,该非特权身份不能创建用于语句日志的etilqs_XXXXX临时文件夹。

我的解决办法是在SQLiteConnection s上设置PRAGMA:

PRAGMA temp_store_directory='<same_path_as_the_database_file>'

我将我的System.Data.SQLite.dll从Robert Simpson编写的1.0.66.0版本(http://sqlite.phxsoftware.com)升级到SQLite开发团队编写的1.0.74.0版本(http://system.data.sqlite.org),这似乎解决了问题。

我知道这个问题是旧的,但我昨天刚刚有同样的问题,正在寻找答案。在我的例子中,我的开发环境是正常的,而生产是失败的。问题是在我的生产网站的下面一行。配置:

<connectionStrings>
    <add name="SalesForceConnection"
        connectionString="metadata=res://SalesForceDataModel.csdl|res://SalesForceDataModel.ssdl|res://SalesForceDataModel.msl;
        provider=Devart.Data.Salesforce;
        provider connection string=&quot;
        User Id=myUserId;
        Password=myPassword;
        Security Token=myToken;
        Persist Security Info=True;
        Host=login.salesforce.com;
        Data Cache=c:'projects'salesforce'1.db;
        Metadata Cache=c:'projects'salesforce'1_Metadata.db&quot;"
        providerName="System.Data.EntityClient" />
</connectionStrings>
数据缓存和元数据缓存都指向我的开发环境中的目录。由于连接字符串很长,我错过了这2个设置。我将目录更改为生产服务器上的目录,并且一切正常。