默认的 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。