SQLite: исключение «Невозможно открыть файл базы данных» при транзакции с несколькими командами - PullRequest
2 голосов
/ 14 июля 2011

У меня есть следующий (упрощенный) код:

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 ]

1 голос
/ 22 ноября 2013

У меня была та же проблема с 1.0.87 и 1.0.89, и в конце концов (с помощью procmon) выяснили причину. На самом деле это вводящее в заблуждение сообщение об ошибке, поскольку не сам файл базы данных, доступ к которому запрещен, а журнал операторов SQLite.

Несмотря на то, что файл базы данных SQLite и журнал создаются в правильном расположении, а разрешения для этой папки разрешают доступ всем, SQLite все еще использует %TEMP% для своего журнала выписок. %TEMP% сопоставляет временную папку под профилем пользователя удостоверения, на котором запущена служба. Поэтому, когда непривилегированная идентификационная информация клиента попадает в службу (и олицетворяется внутри и позади службы), эта непривилегированная идентификационная информация не может создать временную папку etilqs_XXXXX, используемую для журнала операторов.

Мое исправление состояло в том, чтобы установить PRAGMA на SQLiteConnection с:

PRAGMA temp_store_directory='<same_path_as_the_database_file>'
0 голосов
/ 27 июля 2015

Я знаю, что эти вопросы старые, но у меня вчера была такая же проблема, и я искал ответы.В моем случае моя среда разработки работала, а производство не работало.Проблема заключалась в следующей строке в моем производственном файле 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>

Кэш данных и кэш метаданных указывают на каталоги в моей среде разработки.Поскольку строка подключения очень длинная, я пропустил эти 2 настройки.Я изменил каталоги на производственный сервер, и все заработало.

0 голосов
/ 24 августа 2011

Я обновил свой System.Data.SQLite.dll с версии 1.0.66.0, написанной Робертом Симпсоном (http://sqlite.phxsoftware.com), до версии 1.0.74.0, написанной командой разработчиков SQLite (http://system.data.sqlite.org)), и это, похоже, решает проблему.

...