SQLite:“无法打开数据库文件”异常与具有多个命令的事务

时间:2011-07-14 14:30:05

标签: c# sqlite system.data.sqlite

我有以下(简化)代码:

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 Framework,我的System.Data.SQLite版本是1.0.66.0。

任何想法?

提前致谢,

马克

3 个答案:

答案 0 :(得分:1)

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

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

我的解决方法是在PRAGMA上设置SQLiteConnection

PRAGMA temp_store_directory='<same_path_as_the_database_file>'

答案 1 :(得分:0)

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

答案 2 :(得分:0)

我知道这些问题已经过时但我昨天遇到了同样的问题并且正在寻找答案。就我而言,我的开发环境正在运行,生产失败了。问题是我的生产web.config中的以下行:

<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>

数据缓存和元数据缓存都指向我的开发环境中的目录。由于连接字符串很长,我错过了这两个设置。我将目录更改为生产服务器上的目录,这一切都有效。