1

我在两个服务项目之间共享的程序集中有一个 DbContext。我将两个项目都设置为在 Visual Studio 中进行调试。这会创建一个竞争条件,其中DatabaseInitializer每个服务都尝试在启动时更新数据库。

为了防止这种情况,我将我的修改DbContext如下,以防止DatabaseIntializer自动注册。

public EntityContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer<EntityContext>(null);
    }
}

我想禁用DatabaseInitializer内部DbContext本身,这样我就不必SetInitializer()在碰巧引用 my 的每个项目中重复该调用DbContext,并且根据我读过的内容,覆盖OnModelCreating()似乎是这样做的方法。

这可以防止DatabaseInitializer自动运行,但我想创建一个单独的项目,我可以手动运行以更新数据库。所以我做了如下的事情:

static void Main(string[] args)
{
    Database.SetInitializer(new CreateDatabaseIfNotExists<EntityContext>());
    new EntityContext().Database.Initialize(true);
}

问题是这似乎不起作用 -OnModelCreating()方法中设置的 null 初始化程序显然覆盖了我在任何其他调用中指定的任何内容SetInitializer()。即使我将SetIntializer(null)调用移至EntityContext类的静态构造函数以保证首先调用它,它仍然不起作用。它起作用的唯一方法是,如果我手动调用初始化程序,如下所示:

static void Main(string[] args)
{
    new CreateDatabaseIfNotExists<EntityContext>()
        .InitializeDatabase(new EntityContext());
}

但是DatabaseInitializer.InitializeDatabase()直接调用似乎并不正确,因为实体框架基础设施应该调用它。

这是 EF Code First 中的错误吗?解决这个问题的“正确”方法是什么?

更新:我认为使用Update-Database包管理器控制台命令手动创建数据库脚本比这个试图以编程方式更新数据库的 kludgey 项目更好。

4

1 回答 1

1

只要在调用禁用初始化程序之后调用设置初始化程序,这应该可以工作。在您的情况下, OnModelCreating 或静态 EntityContext 初始化程序都不会这样做。仅当您第一次使用 EntityContext 时才会调用静态初始化程序,在您的示例中直到调用 SetInitializer 之后才会调用。

您可以考虑在调用 SetInitializer 之前强制调用静态初始化程序。例如,这应该有效:

using (var context = new EntityContext())
{
    Database.SetInitializer(new CreateDatabaseIfNotExists<EntityContext>());
    context.Database.Initialize(true);
}
于 2012-11-01T20:12:37.730 回答