@jrummell 只是部分正确。如果您将其留给自己的设备,实体框架将为每种 DbContext 类型创建一个数据库。使用 @NeilThompson 从 Julie Lerhman 提到的“有界上下文”的概念,您所做的实际上就是告诉每个上下文实际使用相同的数据库。Julie 的方法使用通用模式,因此实现它的每个 DbContext 最终都在同一个数据库上,但您可以为每个 DbContext 手动执行,如下所示:
public class MyContext : DbContext
{
public MyContext()
: base("name=DatabaseConnectionStringNameHere")
{
Database.SetInitializer(null);
}
}
换句话说,Julie 的方法只是设置了一个基类,您的每个上下文都可以从该基类继承,它会自动处理这部分内容。
这做了两件事:1)它告诉您的上下文使用特定的数据库(即,与所有其他上下文相同)和2)它告诉您的上下文禁用数据库初始化。最后一部分很重要,因为这些上下文现在基本上被视为数据库优先。换句话说,您现在没有可以实际导致创建数据库或发出需要进行迁移的信号的上下文。因此,您实际上需要另一个“主”上下文,其中包含应用程序中的每个实体。但是,除了创建迁移和更新数据库之外,您不必将此上下文用于其他任何事情。对于您的代码,您可以使用更专业的上下文。
使用专门的上下文要记住的另一件事是,每个上下文的每个实例都代表一个独特的状态,即使它们共享实体也是如此。例如,Cat
一个上下文中的实体与第二个上下文中Cat
的实体不同,即使它们共享相同的主键。Cat
如果您从第一个上下文中检索,更新它,然后尝试通过第二个上下文保存它,您将收到错误。该示例有点做作,因为您不太可能在两个不同的上下文中明确拥有相同的实体,但是当您进入外键关系等时,遇到此问题更为常见。即使您没有明确声明DbSet
对于一个相关实体,它在上下文中的一个实体依赖于它,EF 会隐式地DbSet
为它创建一个。这就是说,如果您使用专门的上下文,您需要确保它们是真正专门的,并且在任何级别的相关项目上都存在零交叉。