1

我正在开发一个使用 Entity Framework 5、数据库迁移和 asp 成员 api 的 MVC4 应用程序。在我的开发环境中,我可以完全删除我的数据库,运行一个包(.zip),刷新页面,一切都按预期工作;创建一个数据库,调用种子方法,并将一些默认值卡在数据库中。

完美,也很简单!但是......是的,总是有一个但是!

当我去部署同一个包(只更改了数据库连接字符串)并在远程环境中运行它时,行为会发生变化。同样,如果我进入并完全删除数据库,运行包 (.zip),刷新页面,则仅使用 asp 成员 api 表创建数据库。我检查了连接字符串,这是肯定的,不是原因,否则无法创建数据库和成员表。

我知道使用 nuget 包管理器,它实际上是一个 powershell 实例,但我没有使用它,因为它不能在生产环境中使用。我希望包能够处理这一切,并且在我的测试环境中,它可以完美运行。

有没有人有什么建议?这可能是混合迁移历史的副作用吗?

提前致谢!

4

1 回答 1

4

默认的 MVC4 Internet Application 项目搞砸了很多人。Microsoft 想要演示 SimpleMembership 功能,该功能需要 EF 上下文,但您必须实际修改此部分才能有效地使用应用程序的其余部分,这不是常识。

因此,关于 Entity Framework 如何工作的一些入门知识将有助于弄清楚我认为为什么会发生这种情况。

实体框架(至少版本 5,可能会在 6 或后续版本中更改)只允许您的应用程序使用一个 DbContext。最有可能的是,您至少有两个,一个AccountsContext是由项目模板自动生成的,另一个是您用于应用程序其余部分的上下文。如果您要关闭自动迁移并尝试生成迁移,EF 会很有帮助地告诉您需要指定要使用的上下文。但是,自动迁移是 Code First 中的默认设置,很少有人禁用它,因此很少有人会收到警报。

当启用自动迁移并且您没有现有数据库时,EF 会愉快地(并且默默地)从您的上下文中为您创建数据库。但是,如果您有多个上下文怎么办?嗯,EF 的另一个讨厌的小特性是它可以即时创建数据库。因此,使用哪个上下文是首先访问哪个上下文的函数。不错吧?因此,如果您尝试执行诸如登录之类的任何操作,则会从 中创建数据库AccountsContext,然后,当您尝试从应用程序的上下文中访问某些内容时,该数据库已经存在,而 EF什么也不做。

那么,该怎么办呢?好吧,您需要一个上下文来消除歧义。如果你想在你的应用程序中仍然可以有多个上下文,但你必须基本上告诉 EF 所有其他上下文都是数据库优先的,即不做任何事情。

public class AccountsContext : DbContext
{
    public AccountsContext()
        : base("name=YourConnectionStringName")
    {
        Database.SetInitializer<AccountsContext>(null);
    }

    ...
}

public class MyAppContext : DbContext
{
    public MyAppContext()
        : base("name=YourConnectionStringName")
    {
    }

    // All your entities here, including stuff from AccountsContext

}

MyAppContext将是您的“主”上下文,它将包含 EF 应该知道的数据库中的每个实体。对两者的base调用有助于消除 EF 的猜测,并明确确保每个人都对应该使用什么数据库连接是同一页。您AccountsContext现在基本上是数据库优先的,因此它不会触发 EF 来创建数据库或尝试任何迁移——这就是MyAppContext目的。您可以创建其他上下文,就像AccountsContext分解应用程序的功能一样;您只需要将任何DbSet属性声明镜像到您的“主”上下文中。

Julie Lehrman 在她的书Programming Entity Framework: DbContext中将此概念称为“有界上下文” ,并提供了一个通用类,您可以从中继承所有“有界上下文”,因此您不必指定连接字符串名称和设置每次都将数据库初始化程序设置为 null。

于 2013-04-15T22:32:33.277 回答