【问题标题】:Where to put Seed data using EF5 code-first migrations使用 EF5 代码优先迁移将种子数据放在何处
【发布时间】:2013-05-14 22:09:08
【问题描述】:

我从 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() 方法 - 生成的 cmets 暗示这是放置种子数据的正确位置。所以我是这样填写的:

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 时,它会在 Blah 表中填充 2 条记录“bum”和“moo”。都很好。

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

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

class BlahContextInitializer : DropCreateDatabaseAlways<BlahContext>

然后 Application_Start 看起来像:

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

然后在 BlahContextInitializer.Seed() 方法中包含虚拟数据。此策略是否仅适用于 EF4.1?

我应该将我的种子数据放在 EF5 中的哪个位置,这样它才不会在应用程序启动时被清除?

【问题讨论】:

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


    【解决方案1】:

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

    如果您使用迁移,则应使用 MigrateDatabaseToLatestVersion 初始化程序。
    或者一起跳过初始化程序 - 如果您计划手动迁移 Db(使用 Update-Database)。

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

    记住Migration Seed runs with each start of the application,所以它有点不同(与“典型”种子)。


    如果你有一些复杂的场景(这真的需要你有一个典型的“种子”和你的初始化程序(就像以前做过的那样)——那么请参阅我的这篇关于如何创建这样的自定义初始化程序的帖子......

    What is the correct use of IDatabaseInitializer in EF?

    How to create initializer to create and migrate mysql database?

    【讨论】:

    • 我没有意识到如果使用“update-database”我可以跳过初始化程序。另外我从来不知道 MigrateDatabaseToLatestVersion,它看起来应该可以工作,我会试一试。
    【解决方案2】:

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

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

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

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

    另外,因为它是迁移而不是重新创建数据库,它不会清除那里的任何额外数据,因此它可以用于生产数据库(这是我使用 EF CF 的另一个担忧)

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 我看到了那个方法,但这意味着有一个 BlahContextInitializer.Seed() 和 Configuration.Seed()。由于我的 EF5 项目在我使用“启用迁移”时生成了 Configuration.Seed(),我猜想 BlahContextInitializer.Seed() 是 EF4.1 的东西。
      • 我想。如果生成了 Configuration.Seed() ,则使用它是您最好的选择。
      猜你喜欢
      • 2012-08-19
      • 1970-01-01
      • 1970-01-01
      • 2017-03-27
      • 2018-02-24
      • 1970-01-01
      • 2015-06-26
      • 2012-05-29
      • 1970-01-01
      相关资源
      最近更新 更多