使用EF5代码优先迁移在何处放置种子数据

时间:2013-05-14 22:09:08

标签: asp.net-mvc ef-code-first entity-framework-5

我开始使用EF和MVC,并且遵循不同的教程提供了关于在我的数据库中放置虚拟测试数据的正确位置的不同令人困惑的想法。

所以我做了一些POCO课程,我有一个BlahContext

public class BlahContext : DbContext
{
    public DbSet<Blah> Blahs { get; set; }

    public BlahContext() : base("DefaultConnection")
    {
        Configuration.ProxyCreationEnabled = false;
    }
}

然后在Global.asax.cs中我像这样初始化数据库:

protected void Application_Start()
{
    Database.SetInitializer(new DropCreateDatabaseAlways<BlahContext>());
}

现在我在软件包管理器控制台中执行了以下操作:

PM>  enable-migrations -contexttypename Blah.Models.BlahContext
PM>  add-migration Initial
PM>  update-database

这创建了Configuration.cs,并且在该类中有一个Seed()方法 - 生成的注释意味着这是放置种子数据的正确位置。所以我这样填写:

internal sealed class Configuration : DbMigrationsConfiguration<Blah.Models.BlahContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(Blah.Models.BlahContext context)
    {
#if DEBUG
        context.Blahs.AddOrUpdate(b => b.ID,
            new Blah() { ID = 1, Name = "bum", },
            new Blah() { ID = 2, Name = "moo", }
        );
#endif
    }
}

现在当我再次运行update-database时,它会用2条记录“bum”和“moo”填充Blah表。一切都好。

但是当我运行应用程序时,似乎Database.SetInitializer()中的Application_Start调用会导致重新创建数据库,但这次Configuration.Seed()方法打来电话。所以数据不再存在。

我看到其他一些教程创建了一个类,如:

class BlahContextInitializer : DropCreateDatabaseAlways<BlahContext>

然后Application_Start看起来像:

protected void Application_Start()
{
    Database.SetInitializer(new BlahContextInitializer());
}

然后在BlahContextInitializer.Seed()方法中包含虚拟数据。这个策略只适用于EF4.1吗?

我应该将我的种子数据放在EF5中,以便在应用程序启动时不会被删除?

3 个答案:

答案 0 :(得分:2)

  

但是当我运行应用程序时,似乎是Database.SetInitializer()   在Application_Start中调用会导致重新创建数据库,但是   这次没有调用Configuration.Seed()方法。所以数据   不再存在

如果您正在使用迁移,则应使用MigrateDatabaseToLatestVersion初始值设定项 或者一起跳过初始化程序 - 如果您打算手动迁移Db(使用Update-Database)。

问题是你有two different initializers(或准确的初始化场景)试图一起工作。这有完全不同的'计划'。这是任何其他的问题,但尤其是DropCreateDatabaseAlways并且无法正常工作

请记住Migration Seed runs with each start of the application,所以它有点不同(比'典型'种子)

<小时/> 如果你有一些复杂的场景(真的需要你有一个典型的“种子”与你的初始化程序(就像之前做过) - 然后看到我的这篇文章如何创建像这样的自定义初始化程序...

< / p>

What is the correct use of IDatabaseInitializer in EF?

How to create initializer to create and migrate mysql database?

答案 1 :(得分:1)

感谢@NSGaga,这就是我最终的结果:

protected void Application_Start()
{
    Database.SetInitializer(
        new MigrateDatabaseToLatestVersion<BlahContext, Blah.Migrations.Configuration>()
    );
}

这将更新数据库,然后按预期调用Configuration.Seed()。

现在,如果我更改模型,我仍然需要运行add-migration SomeChange,但我不需要再费心update-database了。每当我运行应用程序时,它都会自动更新数据库。

另外,因为它正在迁移而不是重新创建数据库,所以它不会消​​除任何额外的数据,所以它可以用于生产数据库(这是我担心使用EF CF的另一个问题)

答案 2 :(得分:0)

您可以将种子数据放入“BlahContextInitializer”中。您将它设置为删除并在构建时重新创建数据库,这将擦除所有数据,然后将其重新插入表中。如果您希望它在将DropCreateDatabaseAlways更改为其他设置时将其播种,或者在您最初播种数据后从global.asax注释掉初始化程序。