10

使用 WPF 和实体框架时,我有一个 APP.CONFIG,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
     <add name="DatabaseEntities" connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlServerCe.4.0;provider connection string=&quot;Data Source=%APPDATA%\Folder\Database.sdf&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>

使用此代码时,它总是会引发以下错误:

System.Data.EntityException: The underlying provider failed on Open. ---> System.Data.SqlServerCe.SqlCeException: The path is not valid. Check the directory for the database. [ Path = %APPDATA%\Folder\Database.sdf ]

当我从命令提示符运行路径“%APPDATA%\Folder\Database.sdf”时它工作正常,如果我删除“%APPDATA% 并硬编码路径它工作正常 - 所以它看起来就像 %APPDATA% 是只是没有被实际文件夹取代......

谢谢,

4

3 回答 3

26

正如您已经意识到的那样,%APPDATA%或者任何其他环境变量都不会被连接字符串中它们各自的值替换。环境变量是与操作系统外壳相关的东西。它们在命令提示符下工作,因为命令提示符显式解析输入的值并替换环境变量。这不是 .NET 框架通常执行的操作。

要实现这一点,您必须手动提供%APPDATA%(使用Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)Environment.GetEnvironmentVariable("APPDATA"))的值。有两种选择:

  1. 更改连接字符串并使用|DataDirectory|

    <connectionStrings>
      <add name="DatabaseEntities" connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlServerCe.4.0;provider connection string=&quot;Data Source=|DataDirectory|\Database.sdf&quot;" providerName="System.Data.EntityClient" />
    </connectionStrings>
    

    (注意在|DataDirectory|数据库文件路径中的使用。)

    |DataDirectory|然后在应用程序的 Main 方法中提供值:

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

    有关详细信息,请参阅此 MSDN 页面

  2. 手动为您的 ObjectContext 类提供连接字符串。这样您就可以解析和更改连接字符串:

    public static string GetConnectionString()
    {
        var conStr = System.Configuration.ConfigurationManager.ConnectionStrings["DatabaseEntities"].ConnectionString;
        return conStr.Replace("%APPDATA%",
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
    }
    

    然后:

    var db = new DatabaseEntities(GetConnectionString());
    

    或者子类化你ObjectContext的类并始终使用新的连接字符串:

    public class MyDatabaseEntities : DatabaseEntities
    {
        public MyDatabaseEntities()
            : base(GetConnectionString())
        {
        }
    
        public static string GetConnectionString()
        {
            var conStr = System.Configuration.ConfigurationManager.ConnectionStrings["DatabaseEntities"].ConnectionString;
            return conStr.Replace("%APPDATA%",
                Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
        }
    }
    

    并在任何地方使用新类。

于 2013-02-23T07:07:02.290 回答
4

我有另一个选择。我们不需要更换任何东西。我正在使用下面的连接字符串,没有任何替换,它工作正常。

<connectionStrings>
    <add name="ProjectManagementDBEntities" connectionString="metadata=res://*/Models.ProjectManagementModels.csdl|res://*/Models.ProjectManagementModels.ssdl|res://*/Models.ProjectManagementModels.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=(LocalDB)\MSSQLLocalDB;attachdbfilename=|DataDirectory|\ProjectManagementDB.mdf;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient"/>
  </connectionStrings>

主要变化是data source=(LocalDB)\MSSQLLocalDB;attachdbfilename=|DataDirectory|\ProjectManagementDB.mdf;integrated security=True;

我希望这会拯救一个人。

于 2017-07-23T04:46:57.110 回答
1

您必须%APPDATA%用相对路径替换代码中的 -

var connectionString = ConfigurationManager.ConnectionStrings["DatabaseEntities"]
                                                           .ConnectionString;    
connectionString.Replace("%APPDATA%", 
  Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
于 2013-02-23T07:38:32.910 回答