Matthew
Matthew

Reputation: 4339

How is location of |Data Directory| in connection strings resolved?

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:

<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:

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.

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").

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?

Upvotes: 3

Views: 2870

Answers (1)

Hamid Pourjam
Hamid Pourjam

Reputation: 20764

Here is the code which specifies where is |DataDirectory|

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

Upvotes: 2

Related Questions