我正在开发一个使用Entity Framework 5,数据库迁移和asp成员资格api的MVC4应用程序。在我的开发环境中,我可以完全删除我的数据库,运行包(.zip),刷新页面,所有工作都按预期工作;创建一个数据库,调用种子方法,并将一些默认值粘贴到数据库中。
完美,真的很容易!但是......是的,总有一个但是!
当我去部署这个相同的包(只更改了数据库连接字符串)并在远程环境中运行时,行为会发生变化。同样,如果我进入并完全删除数据库,运行包(.zip),刷新页面,只使用asp成员资格api表创建数据库。我检查了连接字符串,这是肯定的,不是原因,否则无法创建数据库和成员资格表。
我知道使用nuget包管理器,它实际上是一个powershell实例,但我没有使用它,因为它不能在生产环境中使用。我希望这个包可以处理所有这些,在我的测试环境中,它可以完美地运行。
有没有人有任何建议?这可能是混合移民历史的副作用吗?
提前致谢!
答案 0 :(得分:4)
默认的MVC4 Internet Application项目会让很多人感到困扰。 Microsoft希望演示SimpleMembership功能,这需要EF上下文,但是您必须实际修改此部分以有效使用应用程序的其余部分并不常见。
因此,关于实体框架如何运作的一些小知识将有助于澄清我认为这种情况发生的原因。
实体框架(至少版本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
将是您的主人&#34;上下文,它将包含数据库中EF应该知道的每个实体。两者上的base
调用可以使EF的猜测不受影响,并明确确保每个人都应该使用与应该使用的数据库连接相同的页面。您的AccountsContext
现在基本上是数据库优先的,所以它不会激发EF来创建数据库或尝试任何迁移 - 这是MyAppContext
的用途。您可以使用与AccountsContext
相同的方式创建其他上下文,以分解您应用的功能;你只需要将任何DbSet
属性声明镜像到你的&#34; master&#34;上下文。
Julie Lehrman将这一概念称为“有限的背景”。在她的书Programming Entity Framework: DbContext中,并提出了一个通用课程,你可以继承你所有的有限背景&#34; from,因此您不必指定连接字符串名称,并且每次都将数据库初始化程序设置为null。