在appdata文件夹中创建sql server压缩文件

时间:2011-10-03 19:25:19

标签: c# entity-framework-4.1 sql-server-ce

我正在开发一个简单的软件,它首先使用Entity Framework代码,然后使用sql server compact 4.此时此设置可以正常工作。实体框架创建sql server压缩文件(如果它尚不存在)。数据库的路径是从存储在app.config文件中的连接字符串中定义的。它是这样构建的:

<connectionStrings>
  <add name="DataContext" 
       connectionString="Data source=Database.sdf;"
       providerName="System.Data.SqlServerCe.4.0"/>
</connectionStrings>

但是,我想将数据库放在当前用户的Application Data文件夹(win7机器上的C:\ Users \ User \ AppData \ Roaming文件夹)中的文件夹中。我已经尝试将connectionstring的数据源设置为%APPDATA%\ Database.sdf,但是这不起作用,我得到了“路径中的非法字符”异常。

我想坚持使用connectionstring方法,因为我想为我的单元测试使用不同的数据库而不是我的实际应用程序。这样,通过将app.config文件放在项目的根目录中,可以很容易地修改数据库。

有人能引导我朝着正确的方向前进吗?

2 个答案:

答案 0 :(得分:22)

使用以下:

AppDomain.CurrentDomain.SetData("DataDirectory", Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));

<connectionStrings>
  <add name="DataContext" 
       connectionString="Data source=|DataDirectory|Database.sdf;"
       providerName="System.Data.SqlServerCe.4.0"/>
</connectionStrings>

答案 1 :(得分:3)

    connectionString="Data source=Database.sdf;"

这告诉您的应用在应用的当前工作目录中查找Database.sdf;这可能是任何地方,也可能是不可写的。您需要查看指定的位置:

    connectionString="Data source=|DataDirectory|Database.sdf;"

ADO.NET在连接字符串中查找管道字符,并将它们扩展为应用程序域中该名称的属性值。那么DataDirectory属性的价值是多少?它应该由您部署的应用程序设置:

  • .MSI安装程序将其设置为应用程序安装文件夹。如果您允许用户选择安装文件夹,他们也会选择DataDirectory。这就是为什么你应该总是使用|DataDirectory|而不是硬编码路径。
  • ClickOnce在项目中定义了一个特殊的数据文件夹。
  • 网络应用使用App_Data文件夹。
  • Visual Studio调试器使用调试文件夹。

项目中具有“复制到输出目录”属性的任何Visual Studio文件都将复制到DataDirectory。在大多数情况下,DataDirectory将是一个只读文件夹。如果您的数据是只读的,那么这很好,但如果您想要写入数据,则必须将数据复制到可写入的位置。可能最好的地方是Environment.GetFolderPath( Environment.SpecialFolder.ApplicationData))。有几种方法可以做到这一点:

  • 如果您要创建一个空的新数据文件,只需使用您的API标准CREATE DATABASEnew SqlCeConnection()或其他任何内容。
  • 如果要从预先填充的种子或入门数据库开始,请在项目中包含种子数据库。在应用程序启动时,检查SpecialFolder.ApplicationData文件夹中是否存在数据库,如果不存在,则将其复制到那里。

如果您在网上搜索有关创建本地数据库的示例代码,您将遇到很多错误的建议。请勿执行以下操作:

new SqlCeConnection(@"Data source=c:\users\me\myApp\Database.sdf;");  // Do NOT do this!

我希望我不必解释为什么对数据路径进行硬编码是错误的;但请注意,除非在连接字符串中指定完整路径,否则路径相对于当前工作目录。

using (var conn = new SqlCeConnection(@"Data source=|DataDirectory|Database.sdf;"))
{
    conn.Open();
    // No No No! This throws an Access Exception for Standard users,
    // and gets deleted when you repair the app!
    var cmd = conn.CreateCommand("INSERT INTO Table (column1, column2) VALUES (@p1, @p2)");
    ...
}

请勿尝试修改DataDirectory中的数据。该目录不仅不总是可由用户修改,而且由安装程序拥有,而不是由用户拥有。修复或卸载应用程序将删除所有用户的数据;用户不喜欢这样。而是将已安装的数据复制到用户可写的文件夹中,并对副本进行所有更改。

AppDomain.CurrentDomain.SetData("DataDirectory",
    // Wrong, this overwrites where the user installed your app!
    Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));

不要在代码中更改DataDirectory的值,它由安装程序设置,如果您更改它,则无法知道数据的安装位置。如果要创建空数据库,只需在最终位置打开它。如果要打印副本,请打开已安装的数据库,将其保存到用户所在位置,关闭已安装的数据库,然后打开副本。

我也不鼓励将数据保存到Environment.SpecialFolder.CommonApplicationData。用户可能无法写入,除非有一个非常好的理由,必须允许所有用户更改其他用户的数据,每个用户都应拥有自己的数据库。