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

JSc*_*rtz 9 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>
Run Code Online (Sandbox Code Playgroud)

使用此代码时,它始终抛出以下错误:

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 ]
Run Code Online (Sandbox Code Playgroud)

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

谢谢,

Moh*_*han 23

已经重新初始化,%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>
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    AppDomain.CurrentDomain.SetData("DataDirectory",
        Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
    
    Run Code Online (Sandbox Code Playgroud)

    有关更多信息,请参阅此MSDN页面.

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

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

    然后:

    var db = new DatabaseEntities(GetConnectionString());
    
    Run Code Online (Sandbox Code Playgroud)

    或者是您的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));
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    并在任何地方使用新类.