连接字符串中的%APPDATA%不替换实际文件夹?

时间:2013-02-23 06:44:23

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

当使用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%只是没有替代实际的文件夹...

谢谢,

3 个答案:

答案 0 :(得分:22)

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

要实现此目的,您必须手动提供%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|。)

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

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

    请参阅this MSDN page for more information

  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));
        }
    }
    

    并在任何地方使用新课程。

答案 1 :(得分: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;

我希望这会拯救某人。

答案 2 :(得分:1)

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

var connectionString = ConfigurationManager.ConnectionStrings["DatabaseEntities"]
                                                           .ConnectionString;    
connectionString.Replace("%APPDATA%", 
  Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);