我使用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;
**已确定的问题:
我找到的解决方案:
我真的不喜欢这些解决方案。并希望从程序Files目录运行我的工具,因为它是较大项目的一部分。
注意:数据库文件位于programdata目录中。它是由工具创建的(有效)。
编辑:我只是尝试将数据库文件放在C:\Users\Nacereddine\AppData\Roaming\MyTool
中,而在C:\Program Files (x86)\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文件已加密。
答案 0 :(得分:1)
对麻烦的人表示抱歉。
问题是我们在ProgramFiles中使用该工具安装了本地化db文件。
让我从调查中排除的是,打开此文件时,我将OpenMode
设置为ReadOnly
FConnection.Params.Add('OpenMode=ReadOnly');
但是正如我之前在我的问题中所说的,SQLite引擎要求对包含db文件的文件夹具有完全访问权限,因此它对它执行了锁定(仍然找不到我在其中阅读的页面)。
我通过玩开放模式并每次调试工具来进行检查。 一旦我更改了文件和目录的权限,错误就消失了。
最后,我决定将本地化文件与主数据库文件一起移动到programData目录,一切都很好。
我意识到(谢谢您的@Ken和@David)programData目录也需要管理员权限才能写入,因此我将db文件移动到了更合适的目录(即Users)。
此问题有用的是,即使使用OpenMode=ReadOnly
连接到Sqlite db文件,您仍然需要对该文件路径的写访问权限。