使用Delphi和Firedac设置sqlite数据库的相对路径

时间:2017-05-22 23:57:37

标签: sqlite delphi relative-path firedac

取代我的previous question令人困惑且配方不合理,这里是"真正的"问题

我想知道如何在运行时使用Firedac设置位于应用程序文件夹子文件夹中的sqlite数据库的相对路径。

正如Jerry Dodge所述:

  

任何应用程序都不应该依赖同一目录中的可写数据。此外,即使您这样做,也应确保所有路径至少与应用程序相关。

目前,我想到的应用程序是可移植的,我希望数据库文件存储在主exe文件夹的子文件夹中。

在我的主表单的Form.Create事件中,首先使用

path := ExtractFilePath(Application.ExeName);

然后为FDConnection:

with FDConnection1 do begin
  Close;
  with Params do begin
    Clear;
    Add('DriverID=SQLite');
    Add('Database='+path+'Data\sqlite.db');
  end;
  Open;
end;

我继续收到错误说"无法打开数据库文件"。

我不想在FiredDac连接编辑器中设置数据库文件的路径,因为它绝对是绑定到我的机器上的,对吗?

如何将此路径设置为数据库文件,以便在用户放置应用程序文件夹的任何位置都可以使用它?

提前谢谢大家

数学

4 个答案:

答案 0 :(得分:1)

当我找到自己的解决方案时,我决定将这里发布给可能遇到相同问题的未来用户(也就是说Delphi初学者级别以及需要将数据库文件链接到他们的项目exe文件)。

第一步是向项目添加数据模块。这是通过转到文件 - >完成的。新 - >其他 - > Delphi文件 - >数据模块 enter image description here

第二步一旦数据模块添加到项目中,当我的主应用程序表单在创建时调用数据库时,我必须确保首先创建数据模块。为了实现这一点,我去了Project - >选项 - >在自动创建的表单列表的第一个位置表单并拖动数据模块 enter image description here

第三步是在数据模块上放弃FDConnection并设置所有参数 EXCEPT 数据库文件。

第四步是将一个OnCreate事件添加到数据模块,以指定相对于应用程序exe和connect的数据库路径。这是这样做的:

procedure TDataModule1.DataModuleCreate(Sender: TObject);
begin
  path := ExtractFilePath(ParamStr(0));

  FDConnection.Params.Add('Database='+path+'Database\sqlite.db');
  FDConnection.Connected := True;
end;

第五步和最后一步是将数据模块添加到需要连接数据库的所有其他单元的uses子句中。

我意识到这个解决方案远非完美,并且正如非常有经验的用户已经说过的那样,将数据库存储在与主应用程序Exe相同的文件夹(或子文件夹)中并不是一个好的解决方案。

此外,我决定在创建DataModule时连接到数据库,但另一种解决方案可能是在触发查询之前按需连接然后断开连接。这取决于您和您的需求

感谢所有人的帮助,提示和建议

数学

PS:请注意我没有将我的答案视为最佳答案,不公平: - )

答案 1 :(得分:0)

在android中,我无法使用设计时打开的fdConnection进行编译,然后证明它已关闭。你的第一行不适合我,但是关于实现目标:

使用以下表达式,它适用于我:

FdConnection1.Params.Values['Database'] := GetHomePath
        + PathDelim + 'sqlite.db';

看看我没有使用子文件夹'Data'。你可以先尝试一下。

答案 2 :(得分:0)

如果你的资源对于最终​​用户来说很轻松,你可以将它们直接打包到exe文件中。这将为您提供真正的便携式应用程序,您的用户可以从任意位置运行,甚至可以从USB闪存中运行。

转到项目 - >资源和图片菜单,在那里添加文件。

您可以使用TStream在运行时访问它们:

var
  s:   TStream;
  {.....}
  s:=TResourceStream.Create(hinstance, 'myfile_1', RT_RCDATA);

您可以直接在内存中处理的一些资源。对于sqlite数据库,您可以将其从应用程序资源复制到用户的文档路径:

  MyAppPath := Tpath.GetDocumentsPath+'\MyAppName'; // you need System.IOUtils in uses  
  If not DirectoryExists(MyAppPath) then CreateDir(MyAppPath);
  MyDBPath := MyAppPath+'\Data\sqlite.db';
  If not FileExists(MyDBPath) then begin
    FL:=TFileStream.Create(MyDBPath ,fmCreate);
    FL.CopyFrom(s,0); // this will copy your db into 'sqlite.db' file 
  end;

答案 3 :(得分:0)

<强>简介

IMHO

数据库路径和服务器名称不应在应用程序中进行硬编码。

为什么?

  1. 当您处理项目时,您需要在数据库连接,设置数据集,查询等方面做很多事情。通常这是在工作数据库上完成的。然后,服务器名称和数据库路径与真实数据库的路径不同。
  2. 您应该能够轻松设置服务器名称和数据库路径,而无需编译项目。这允许在随机计算机上正确设置数据库连接参数。
  3. 解决方案:

    1. 在设计时设置数据库连接组件,不要在运行时创建它。将所有参数(包括服务器名称,数据库路径,字符集等)设置到数据库的工作副本。这将允许您在设计时设置与此数据库关联的其他组件。 (在你的回答中,我看到你做的几乎一样。)

    2. 将服务器名称,数据库路径和所需的任何其他参数保存到外部资源,ini文件,Windows注册表或其他内容。然后在应用程序启动时或连接到数据库之前获取这些参数。

      在您的情况下,您使用本地服务器和路径与应用程序相同,因此您不需要存储任何内容。

    3. 关于问题

      代码:

      with FDConnection1 do begin
        Close;
        with Params do begin
          Clear;  <-- this removes all parameters
          Add('DriverID=SQLite');
          Add('Database='+path+'Data\sqlite.db');
        end;
        Open;
      end;
      

      删除除DriverIDDatabase之外的所有其他参数。可能由此引起的错误。

      如果您已在FDConnection中设置所有参数:

      不要使用:

      FDConnection.Params.Add('Database='+path+'Data\sqlite.db');
      

      这将添加具有相同名称的新参数,但连接将使用第一个参数。

      这解释了为什么一切都在您的答案中,因为您没有设置参数&#39;数据库&#39;在设计时间:

        

      第三步是在数据模块上放下FDConnection并设置全部   参数 EXCEPT 数据库文件。

      改为使用:

      FDConnection.Params.Database := 'Database='+path+'Data\sqlite.db'; 
      

      您可以在此处使用此功能   OnDataModuleCreateFDConnectionBeforeConnect次活动

      我希望这会有用。