EF6 代码优先:更新数据库时登录失败

EF6 Code First: Login Failing on update-database

我正在尝试在 EF6 代码优先数据库上执行更新数据库。我所做的只是构建我的模型和数据上下文,运行 启用迁移并执行添加迁移 InitialCreate。一切顺利。

但是更新数据库以两种不同的方式失败。

我让它工作了一段时间,但它正在 c:\Users\ 下创建数据库文件(即 MDF 和日志文件)。我不想让他们在那里。我希望它们位于我正在构建的 MVC 网站的 App_Data 文件夹中(数据库模式位于单独的 class 库 DLL 中,因为 MVC 应用程序和一些数据导入和在控制台应用程序中按摩内容)。

我试图通过调整连接字符串来更改数据库文件的位置,但我的更改要么被忽略(即,数据库文件一直在 c:\Users\ 中创建),要么我 运行进入第二个错误,"Cannot open database ... requested by the login...blah blah blah"。但是我可以在 SSMS 中打开数据库,并且我的 Windows 用户帐户是数据库的所有者。

为了好玩,我尝试从 SSMS 中删除和创建数据库。一切顺利...但是更新数据库命令>>仍然<<无法登录。

如果能帮助解决这个问题,我们将不胜感激!

我的数据上下文的构造函数:

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

class库中的连接字符串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>

更新数据库抛出的最近异常:

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'.

附加信息:

关于连接字符串,我显然有些地方不明白。如果我给连接字符串一个新名称(例如,Council2015a)并更改 CampaignDbContext 中相应的构造函数参数,我就可以让更新数据库工作。但是它创建了一个新的数据库——在 c:\Users\ 下,我不想要它——而不是附加到现有的数据库文件。

此外,如果删除或移动数据库文件(并更新附加文件参数),将再次出现相同的登录失败。

所以某处某处正在记住以前创建的数据库,然后 "refusing" 放手。

这完全违反直觉(包括为什么数据库以连接字符串中的名称参数命名)。

在连接字符串中尝试添加数据库用户名和密码。

我偶然发现了基本问题的答案——如何在你想要的地方创建数据库——这似乎已经解决了我遇到的其他问题。

使用看起来像您期望的连接字符串:

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

但是当您 运行 更新数据库时(在执行您需要执行的任何添加迁移调用之后),确保连接字符串将被更新数据库命令找到.

这听起来应该是自动发生的。如果您在解决方案的启动项目中创建数据库,它确实如此。因为这是更新数据库默认查找连接字符串的地方。

在我的例子中,我在 class 库项目中定义数据 classes,以便我可以在多个应用程序项目中使用它。因此,当我在 class 库项目的 "context" 中 运行 时,更新数据库在错误的位置查找连接字符串。

无论您(和我)怎么想,在包管理器控制台中选择 class 库作为 "Default project" 并不会通知更新数据库的连接字符串搜索过程。

相反,明确指定启动项目:

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

瞧!

现在来谈谈为什么找不到正确的连接字符串——因为我在 class 库项目中使用的 ID 名称甚至没有出现在我的解决方案启动时的连接字符串列表中项目——应该会导致 "user login failure" 错误……好吧,这超出了我的范围:)。还有一个糟糕的软件设计的例子,恕我直言。