繁体   English   中英

如何解决[FireDAC] [Phys] [SQLite]错误:无法在程序文件中安装应用程序时打开数据库文件?

[英]How to solve [FireDAC][Phys][SQLite] ERROR: unable to open database file, When app is installed in programFiles?

我使用Firedac开发了一个工具,并将数据库作为SQLite。

完成项目并制作安装程序(InnoSetup)后,出现错误

[FireDAC] [Phys] [SQLite]错误:无法打开数据库文件

当我启动应用程序(双击)时。

这是我使用的连接参数

constructor TDbInteract.Create(const aDatabasePath: string; const aOnNeedCredentials: TOnNeedCredentials);
var
  aParams: array of string;
begin
  if not TFile.Exists(aDatabasePath) then
    raise Exception.Create('Database file not found');

  aParams := ['DriverID=SQLite',
              'Database=' + aDatabasePath,
              'OpenMode=CreateUTF16',
              'LockingMode=Normal',
              'JournalMode=WAL',
              'StringFormat=Unicode',
              'Synchronous=Full',
              'UpdateOptions.LockWait=True',
              'BusyTimeout=30000',
              'SQLiteAdvanced=temp_store=MEMORY;page_size=4096;auto_vacuum=FULL'];
  InitiateResource(aParams, aOnNeedCredentials);
end;

procedure TDbInteract.InitiateResource(const aParams: array of string; const aOnNeedCredentials: TOnNeedCredentials);
var
  I: Integer;
  Credentials: TStringDynArray;
begin
  FRowsAffected := 0;
  FIsForeignKeyHonored := True;
  FOwnsResultDataSets := True;
  FDataSetContainer := TDataSetContainer.Create(nil);

  FConnection := TFDConnection.Create(nil);
  try
    for I := Low(aParams) to High(aParams) do
    begin
      FConnection.Params.Add(aParams[I]);
    end;

    if Assigned(aOnNeedCredentials) then
    begin
      aOnNeedCredentials(Self, Credentials);

      for I := Low(Credentials) to High(Credentials) do
      begin
        FConnection.Params.Add(Credentials[I]);
      end;
    end;

    FConnection.Open;
  except
    raise;
  end;
end;

**发现的问题:

  1. 我读过某个地方(不记得我所在的页面),SQLite引擎需要完全锁定要写入的目录。 这就是问题所在。 我如何以调用者身份运行该工具,而我的帐户是管理员,所以这不是问题。 另外,我有用C#编写的相同工具,这个问题永远不会发生。

我发现的解决方案:

  1. 以管理员身份运行该工具
  2. 不要在ProgramFiles目录中安装该工具

我真的不喜欢这些解决方案。 并希望从程序Files目录运行我的工具,因为它是较大项目的一部分。

注意 :数据库文件位于programdata目录中。 它是由工具创建的(有效)。

编辑:我只是试图将数据库文件放在C:\\Users\\Nacereddine\\AppData\\Roaming\\MyTool ,但是当该工具安装在C:\\Program Files (x86)\\MyTool时,我仍然C:\\Users\\Nacereddine\\AppData\\Roaming\\MyTool相同的问题

这就是我创建数据库文件的方式

class procedure TDbInteract.CreateSQLiteDb(const aDatabasePath: string; const aTables: TStringDynArray);
var
  I: Integer;
  aParams: array of string;
  aConnection: TFDConnection;
begin
  aParams := ['DriverID=SQLite',
              'Database=' + aDatabasePath,
              'OpenMode=CreateUTF16',
              'LockingMode=Normal',
              'JournalMode=WAL',
              'StringFormat=Unicode',
              'Synchronous=Full',
              'UpdateOptions.LockWait=True',
              'BusyTimeout=30000',
              'SQLiteAdvanced=temp_store=MEMORY;page_size=4096;auto_vacuum=FULL'];

  aConnection := TFDConnection.Create(nil);
  try
    for I := Low(aParams) to High(aParams) do
    begin
      aConnection.Params.Add(aParams[I]);
    end;

    aConnection.Open();

    for I := Low(aTables) to High(aTables) do
    begin
      aConnection.ExecSQL(aTables[I]);
    end;
  finally
    aConnection.Close;
    aConnection.Free;
  end;
end;

注意:我不知道这是否有区别,但是Db文件已加密。

对不起麻烦的人。

问题是我们在ProgramFiles中使用该工具安装了本地化数据库文件。

使我无法进行调查的原因是,打开该文件时,我将OpenMode设置为ReadOnly

FConnection.Params.Add('OpenMode=ReadOnly');

但是正如我之前在我的问题中所说的那样,SQLite引擎要求对包含db文件的文件夹具有完全访问权限,因此它对它执行了锁定(仍然找不到我在其中阅读的页面)。

我通过玩开放模式并每次调试工具来进行检查。 一旦更改了文件和目录的权限,错误就消失了。

最后,我决定将本地化文件与主数据库文件一起移动到programData目录,一切顺利。

我意识到(谢谢您的@Ken和@David),programData目录也需要写入管理员权限,因此,我将db文件移至更合适的目录(即Users)。

此问题有用的是,即使使用OpenMode=ReadOnly连接到Sqlite db文件,您仍需要对该文件路径的写访问权限。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM