EF6 Code First: Login Failing on update-database

c# ef-code-first entity-framework entity-framework-6

Question

I am trying to do an update-database on an EF6 code first database. All I've done is build my models and the datacontext, run enable-migrations and did an add-migration InitialCreate. That all worked well.

But the update-database is failing in two different ways.

For a while I had it working, but it was creating the database files (i.e., the MDF and log files) under c:\Users\. I don't want them there. I want them in the App_Data folder of an MVC website I'm building (the database schema is in a separate class library DLL because it needs to be accessible to both the MVC app and some data import and massaging stuff in a console app).

I tried to change the location of the database files by tweaking the connection string, but my changes were either ignored (i.e., the database files keep being created at c:\Users\) or I ran into the second error, "Cannot open database ... requested by the login...blah blah blah". Yet I could open the database in SSMS, and my Windows user account is the owner of the database.

For fun I tried deleting and creating the database from within SSMS. That went fine...but the update-database command >>still<< fails to log in.

Any help in unraveling this mess would be much appreciated!

The constructor for my datacontext:

public CampaignDbContext()
    : base( "Council2015", throwIfV1Schema: false )
{
    Database.SetInitializer<CampaignDbContext>( null );
}

The connection string in the class library app.config:

<connectionStrings>
    <add name="Council2015" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=E:\\Programming\\Council2015\\Council2015\\App_Data\\Council2015.mdf;Integrated Security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient"/>
</connectionStrings>

The most recent exception thrown by update-database:

Applying explicit migrations: [201503180506326_InitialCreate].
Applying explicit migration: 201503180506326_InitialCreate.
System.Data.SqlClient.SqlException (0x80131904): Cannot open database "Council2015" requested by the login. The login failed.
Login failed for user 'KENSEI\Mark'.
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
...
Cannot open database "Council2015" requested by the login. The login failed.
Login failed for user 'KENSEI\Mark'.

Additional Info:

There's something I obviously don't understand about connection strings. I can get update-database to work if I give the connection string a new name (e.g., Council2015a) and change the corresponding constructor parameter in CampaignDbContext. But it creates a new database -- under c:\Users\, where I don't want it -- instead of attaching to the existing database file.

Moreover, if you delete the database files, or move them (and update the attach file parameter), once again the same login failure occurs.

So something somewhere is remembering the previously-created databases, and "refusing" to let go.

This is all massively counter-intuitive (including why the database is being named after the name parameter in the connection string).

1
1
3/29/2015 5:31:32 PM

Accepted Answer

I stumbled across the answer to the basic problem -- how to get the database created where you want it -- which appears to have solved the other issues I was encountering.

Use a connection string that looks like you would expect it to have to look:

<add name="Council2015" connectionString="Server=(LocalDB)\v11.0; Integrated Security=true; AttachDbFileName=E:\Programming\Council2015\Council2015\App_Data\Council2015.mdf" providerName="System.Data.SqlClient"/>

But when you run update-database (after doing whatever add-migration calls you need to do), make sure the connection string will be found by the update-database command.

That sounds like it should happen automatically. And it does, if you're creating your database in the startup project for your solution. Because that's where update-database looks for connection strings, by default.

In my case I was defining the data classes in a class library project so that I could use it in multiple application projects. So update-database was looking in the wrong place for connection strings when I ran it within the "context" of the class library project.

Selecting the class library as the "Default project" in the Package Manager Console doesn't, despite what you (and I) might think, inform update-database's search process for connection strings.

Instead, specify the startup project explicitly:

update-database -StartUpProjectName "<class library project name, in my case>"

and voila!

Now as to why a failure to locate the correct connection string -- since the id name I was using in the class library project didn't even appear in the list of connection strings in my solution's startup project -- should have resulted in a "user login failure" error...well, that's beyond me :). And an example of lousy software design, IMHO.

1
3/18/2015 10:17:08 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow