如何解析|数据目录|在连接字符串中的位置?

时间:2021-11-07 14:42:56

If I create an asp.net project and use entity framework to create a database, something like this is automatically added to the connection strings in the web.config:

如果我创建一个asp.net项目并使用实体框架来创建一个数据库,这样的东西会自动添加到web.config中的连接字符串中:

<add name="DefaultConnection" connectionString="data source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\WebAppName.mdf;initial catalog=WebAppName;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />

Note that instead of a fully qualified file path, it uses |Data Directory| which, in this case, points to the 'App_Data` folder. Here's how some of the documentation explains it:

注意,它没有使用完全限定的文件路径,而是使用|数据目录|,在本例中,|指向“App_Data”文件夹。以下是一些文件对此的解释:

The presence of User Instance=true and AttachDBFilename=|DataDirectory| cause SqlConnectionHelper to conclude that the connection string targets SQL Server Express and triggers the database's creation. (The presence of data source=.\SQLEXPRESS in the connection string does not factor into the decision, because SqlConnectionHelper supports non-default as well as default instances of SQL Server Express.) The |DataDirectory| portion of the connection string specifies that the MDF file is located inthe App_Data directory. SqlConnectionHelper derives the database name from the MDF file name. It also creates an App_Data folder to hold the MDF if the folder doesn't already exist.

User Instance=true和AttachDBFilename=|DataDirectory|的出现导致SqlConnectionHelper推断连接字符串以SQL Server Express为目标并触发数据库的创建。(数据源的存在=。\SQLEXPRESS在连接字符串中不影响决策,因为SqlConnectionHelper支持非默认和SQL Server Express的默认实例。连接字符串的|DataDirectory|部分指定MDF文件位于App_Data目录。SqlConnectionHelper从MDF文件名派生数据库名。它还创建一个App_Data文件夹来保存MDF(如果该文件夹不存在)。

Except, if I use Entity Framework in, say, a console application, none of that is true--you'll just get an exception saying there's no file at the specified path, and it will both ignore any App_Data folder you created and fail to create one if there is none. If you remove the AttachDBFilename section altogether, it will work, but will create the database in the local output bin where the .exe file is located. Google tells me you can manually set |Data Directory| using AppDomain.SetData but apparently that's still not true for a console application (get compile error saying "An object reference is required").

但是,如果我在控制台应用程序中使用实体框架,没有一个是正确的——您只会得到一个异常,说在指定的路径上没有文件,并且它会忽略您创建的任何App_Data文件夹,如果没有,则创建失败。如果您完全删除了AttachDBFilename部分,它将会工作,但是会在.exe文件所在的本地输出库中创建数据库。谷歌告诉我可以使用AppDomain手动设置|数据目录|。SetData,但是对于控制台应用程序显然不是这样(获取编译错误,说“需要对象引用”)。

So my question is, how exactly does the location of |Data Directory| get resolved? As far as I know, the fact that it differs between console apps and Asp.net apps means the resolution can't be happening solely in SQL Server Express as both are using the same installation. So is it happening in the asp.net server? Or is there a hidden settings file that gets created in asp.net projects?

我的问题是,|数据目录|的具体位置如何得到解决?据我所知,控制台应用程序和Asp.net应用程序之间的差异意味着解析不能仅在SQL Server Express中进行,因为两者都使用相同的安装。那么这是在asp.net服务器上发生的吗?或者在asp.net项目中创建一个隐藏的设置文件?

1 个解决方案

#1


2  

Here is the code which specifies where is |DataDirectory|

这是指定|DataDirectory|位置的代码

GetDataDirectory

GetDataDirectory

[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
internal static string GetDataDirectory() {
    if (HostingEnvironment.IsHosted)
        return Path.Combine(HttpRuntime.AppDomainAppPath, HttpRuntime.DataDirectoryName);

    string dataDir = AppDomain.CurrentDomain.GetData(s_strDataDir) as string;
    if (string.IsNullOrEmpty(dataDir)) {
        string appPath = null;

#if !FEATURE_PAL // FEATURE_PAL does not support ProcessModule
        Process p = Process.GetCurrentProcess();
        ProcessModule pm = (p != null ? p.MainModule : null);
        string exeName = (pm != null ? pm.FileName : null);

        if (!string.IsNullOrEmpty(exeName))
            appPath = Path.GetDirectoryName(exeName);
#endif // !FEATURE_PAL

        if (string.IsNullOrEmpty(appPath))
            appPath = Environment.CurrentDirectory;

        dataDir = Path.Combine(appPath, HttpRuntime.DataDirectoryName);
        AppDomain.CurrentDomain.SetData(s_strDataDir, dataDir, new FileIOPermission(FileIOPermissionAccess.PathDiscovery, dataDir));
    }

    return dataDir;
}

#1


2  

Here is the code which specifies where is |DataDirectory|

这是指定|DataDirectory|位置的代码

GetDataDirectory

GetDataDirectory

[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
internal static string GetDataDirectory() {
    if (HostingEnvironment.IsHosted)
        return Path.Combine(HttpRuntime.AppDomainAppPath, HttpRuntime.DataDirectoryName);

    string dataDir = AppDomain.CurrentDomain.GetData(s_strDataDir) as string;
    if (string.IsNullOrEmpty(dataDir)) {
        string appPath = null;

#if !FEATURE_PAL // FEATURE_PAL does not support ProcessModule
        Process p = Process.GetCurrentProcess();
        ProcessModule pm = (p != null ? p.MainModule : null);
        string exeName = (pm != null ? pm.FileName : null);

        if (!string.IsNullOrEmpty(exeName))
            appPath = Path.GetDirectoryName(exeName);
#endif // !FEATURE_PAL

        if (string.IsNullOrEmpty(appPath))
            appPath = Environment.CurrentDirectory;

        dataDir = Path.Combine(appPath, HttpRuntime.DataDirectoryName);
        AppDomain.CurrentDomain.SetData(s_strDataDir, dataDir, new FileIOPermission(FileIOPermissionAccess.PathDiscovery, dataDir));
    }

    return dataDir;
}