0
votes

I have a dll that contains EF related code: entities, context and code based configuration. When I run tests on this dll, everything works fine.

I have created a ASP MVC Web Api project and when I invoke the dll from it I get following exception:

“Cannot attach the file 'C:\project\xxx\ MyProj.Persistance.IndicatorsContext.mdf' as database MyProj.Persistance.IndicatorsContext' “

I am using code-based configuration:

 public class MyDbConfiguration : DbConfiguration
 {
    public MyDbConfiguration()
    {
        SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy());
        SetDefaultConnectionFactory(new LocalDbConnectionFactory("v11.0"));

    }
} 

Here is my Context:

[DbConfigurationType(typeof(MyDbConfiguration))] 
public class IndicatorsContext : DbContext
{
    public IndicatorsContext()            
    {
        Debug.Write("Connection String:" + Database.Connection.ConnectionString);
        Database.SetInitializer(new DropCreateDatabaseIfModelChanges<IndicatorsContext>());            
    }
    // etc...
    }
}

The funny thing is, when I take a look at connection string in Context constructor, it is different depending if I run the tests or I run Asp Mvc. I have noted that two connection strings differ:

  1. Data Source=(localdb)\v11.0;Initial Catalog=MyProj.Persistance.IndicatorsContext;Integrated Security=True;MultipleActiveResultSets=True
  2. Data Source=(localdb)\v11.0;AttachDbFilename=|DataDirectory|MyProj.Persistance.IndicatorsContext.mdf;Initial Catalog=MyProj.Persistance.IndicatorsContext;Integrated Security=True;MultipleActiveResultSets=True

Second one is from Asp Mvc and has AttachDbFilename section?

I have commented-out entityFramework tag in my Web.config and left only the following:

<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />

How to get MVC project to use the same connection string I get when i run project from the test?

1

1 Answers

1
votes

You don't specify the connection string to use anywhere, therefore the entity framework creates it for you.

See http://msdn.microsoft.com/en-us/data/jj592674 specifically the section:

Use Code First with connection by convention

If you have not done any other configuration in your application, then calling the parameterless constructor on DbContext will cause DbContext to run in Code First mode with a database connection created by convention.

So having deduced that the connection string is created by convention, its just a matter of working out what that convention is

From: http://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework/Infrastructure/LocalDbConnectionFactory.cs the relevant part is:

    /// <summary>
    /// Creates a connection for SQL Server LocalDb based on the given database name or connection string.
    /// If the given string contains an '=' character then it is treated as a full connection string,
    /// otherwise it is treated as a database name only.
    /// </summary>
    /// <param name="nameOrConnectionString"> The database name or connection string. </param>
    /// <returns> An initialized DbConnection. </returns>
    public DbConnection CreateConnection(string nameOrConnectionString)
    {
        Check.NotEmpty(nameOrConnectionString, "nameOrConnectionString");

        var attachDb = string.IsNullOrEmpty(AppDomain.CurrentDomain.GetData("DataDirectory") as string)
                           ? " "
                           : string.Format(
                               CultureInfo.InvariantCulture, @" AttachDbFilename=|DataDirectory|{0}.mdf; ", nameOrConnectionString);

        return new SqlConnectionFactory(
            string.Format(
                CultureInfo.InvariantCulture,
                @"Data Source=(localdb)\{1};{0};{2}",
                _baseConnectionString,
                _localDbVersion,
                attachDb)).CreateConnection(nameOrConnectionString);
    }

As you can see, AppDomain.CurrentDomain.GetData("DataDirectory") is the reason why you either get the AttachDbFilename section or not

To answer your question: How to get MVC project to use the same connection string I get when i run project from the test?

Be explicit as to what you want the connection string to be.. refer to the first link I posted and choose whichever means you want to set this (e.g. in the web.config, in the constructor, etc)

OR

Ensure your app domain is set up the same way when executing as it is when running the WebApi project e.g.

AppDomain.CurrentDomain.SetData("DataDirectory", path);