发布Windows应用程序后错误的数据库路径

问题描述:

我开发了一个带MS Access数据库的WPF应用程序。一切工作正常。但是,当我尝试发布应用程序以创建安装文件以在其他PC上使用应用程序时,我在第一次运行应用程序时遇到以下异常:发布Windows应用程序后错误的数据库路径

System.Data.OleDbException:Could not找到文件 'C:\ Users \ me \ AppData \ Local \ Apps \ 2.0 \ 77NYD08R.L6A \ Y93TLQGV.2TD \ pier..tion_b5378b5ea7b941ca_0001.0000_9b5c3ff3b52b7eb4 \ Data。

我在代码中访问数据库如下:

private void ConnectToDatabase() 
{ 
    dBConnection.ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=MyProjectDB.mdb"; 
    dBConnection.Open(); 
} 

我在bin/Debug文件夹添加到数据库中。 为什么它试图从AppData\Local文件夹中获取数据库文件?我应该将数据库文件移动到另一个文件夹吗?

+0

你是如何“发布”应用程序的? AppData文件夹*是应用程序应该存储其数据文件的地方。你为数据库使用了一个相对文件路径,这意味着你的代码试图在安装文件夹中找到数据库(只读的'Program Files',由于安全原因,它应该*不可写*)。不知何故,这被重定向到AppData路径 –

+0

我刚刚右键单击项目并单击发布。正如我所知,Windows应用程序没有AppData文件夹。我错了吗? – Hanady

+0

是的。 * Windows *有这个文件夹,就像它有文档,用户等。*所有*应用程序都应该在那里存储他们自己的数据。每个用户的配置文件目录中还有每个用户的数据文件夹。 '发布'不是“只”发布,它创建了一个ClickOnce应用程序,实际上并没有以通常的方式安装(即使用MSI,复制文件等)。该应用程序是按用户安装的,不需要管理权限,自动更新等。这是唯一可能的,因为使用AppData和每个用户文件夹 –

您需要在连接字符串中为您提供访问数据库的位置

dBConnection.ConnectionString = "Provider=MICROSOFT.ACE.OLEDB.12.0; " + 
       "Data Source=|DataDirectory|MyProjectDB.mdb" 

| DataDirectory目录|需要成为一个完整的相对路径,这只是一个占位符。所以,你可以使用

var path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); 

dBConnection.ConnectionString = "Provider=MICROSOFT.ACE.OLEDB.12.0; " + 
       "Data Source=" + path + "\MyProjectDB.mdb" 
+0

不,仍然会得到相同的错误。 – Hanady

+0

什么是您使用的目录路径在连接字符串? –

+0

正如我所提到的,我把数据库文件放在调试文件夹中,并在连接字符串中直接使用'Data Source = | DataDirectory | MyProjectDB.mdb'或Data Source = MyProjectDB.mdb访问它,但两者都不起作用 – Hanady

基本上没有,你应该做的:

不要留在你的项目文件夹中的数据库文件,复制到其他地方,喜欢Environment.SpecialFolder.ApplicationData。您在首次启动应用程序时执行此操作,并且不存在任何数据库文件,因此您将数据库从项目文件夹复制到数据文件夹。

There is quite a good answer, how to deal with the problem here

如果你需要写部署你的可执行文件中的数据,你应该 首先将其复制某个地方,你知道用户将能够写入 到,如Environment.SpecialFolder.ApplicationData,并写入 副本。 DataDirectory不一定是用户可写的,它是部署的一部分而不是用户数据的一部分;如果您 修复或卸载您的可执行文件,然后DataDirectory获得 重新安装或删除。当你删除其 数据用户不喜欢它,所以不要把它保存到DataDirectory目录

您可以通过这个命令得到你的ClickOnce可执行文件的路径:

var exePath = System.IO.Path.GetDirectoryName(
       new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath); 

见然后this answer : 使用类似的东西如果数据库应该由目标计算机的多个用户使用:

AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(System.Environment.GetEnvironmentVariable("public"), YOUR_FOLDER_NAME)); 

或者为一个用户只有一个数据库:

AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),YOUR_FOLDER_NAME)); 

你应该知道,ClickOnce部署方法允许在不安装您的应用程序的本地管理员的用户,所以最好选择在目标机器上这样的文件夹应该是默认的可写为最终用户。

然后你在配置文件中的连接字符串中使用|DataDirectory|,就像上面提到的答案一样。

DataDirectory将是您将exe文件中的mdb文件复制到目标数据文件夹的地方。

您的问题还在于,ClickOnce应用程序安装在用户配置文件中,因此数据库(如果要在1台计算机的不同用户之间共享)应放置在c:\users\public文件夹中的某处。如果仅由单个用户使用,则可以将其放置在文档文件夹中或当前用户配置文件中的某个位置。

所以对于一个共享的数据库,你的第一次部署后,复制您的mdb你的数据库文件夹可能是这样的:一个非共享数据库

Path.Combine(System.Environment.GetEnvironmentVariable("public"), YOUR_FOLDER_NAME) 

这将是

Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),YOUR_FOLDER_NAME) 

通常有一个非常好的理由不会将数据留在项目文件夹中,因为它很清楚recommended by Microsoft here

当卸载ClickOnce应用程序时,其数据目录也被删除,即 。切勿使用数据目录来存储最终用户管理的数据,例如文档。

但是,如果你可以,那么你可能会很好地改变Visual Studio中的文件属性see this answer

但是,当您在项目中使用mdb文件时,本地安装的数据文件会被已发布的ClickOnce更新 - one more link here重写,只是为了查看这是在ClickOnce应用程序启动时在其他位置复制数据的常见方法。

+0

连接字符串*已经*正在查看ApplicationData文件夹。问题是,OP如何使用ClickOnce在那里部署数据库文件?除此之外,除非机器的多个用户使用相同的数据库,否则使用用户的应用程序数据文件夹并不是一件坏事 –

+0

如果应用程序被卸载,数据丢失,那么我相信...? –

+0

与*每个*其他应用程序相同 - 被修改的文件被留下。这也是Windows Installer所做的。文档样式的数据应该放入“文档”文件夹中。这些规则与商店应用程序没有什么不同 –