41

我一直在现有数据库上使用 Entity Framework 4.3,并且我有几个我试图迎合的场景。

首先,如果我删除我的数据库,我希望 EF 从头开始​​重新创建 - 我已成功为此使用了 CreateDatabaseIfNotExists 数据库初始化程序。

其次,如果我更新我的模型并且数据库已经存在,我希望数据库能够自动更新——我已经成功地为此使用了 Entity Framework 4.3 Migrations。

所以这是我的问题。假设我向我的模型添加了一个新表,它需要一些参考数据,这是确保在数据库初始化程序运行和迁移运行时创建这些数据的最佳方法。我的愿望是,当我从头开始创建数据库以及由于迁移运行而更新数据库时,数据会被创建。

在一些 EF 迁移示例中,我看到人们在迁移的 UP 方法中使用 SQL() 函数来创建种子数据,但如果可能的话,我宁愿使用上下文来创建种子数据(如您在大多数数据库初始化程序示例中所见)因为当 EF 的整个想法将其抽象出来时,您会使用纯 sql,这对我来说似乎很奇怪。我尝试在 UP 方法中使用上下文,但由于某种原因,当我尝试将种子数据直接添加到创建表的调用下方时,它认为不存在迁移中创建的表。

任何智慧都非常感谢。

4

2 回答 2

55

如果您想使用实体来播种数据,您应该Seed在迁移配置中使用方法。如果您生成新项目Enable-Migrations,您将获得此配置类:

internal sealed class Configuration : DbMigrationsConfiguration<YourContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(CFMigrationsWithNoMagic.BlogContext context)
    {
        //  This method will be called after migrating to the latest version.

        //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
        //  to avoid creating duplicate seed data. E.g.
        //
        //    context.People.AddOrUpdate(
        //      p => p.FullName,
        //      new Person { FullName = "Andrew Peters" },
        //      new Person { FullName = "Brice Lambson" },
        //      new Person { FullName = "Rowan Miller" }
        //    );
        //
    }
}

迁移播种数据的方式不是很有效,因为它应该用于一些非常基本的播种。每次对新版本的更新都会经过整个集合并尝试更新现有数据或插入新数据。如果您不使用AddOrUpdate扩展方法,则必须手动确保仅在数据不存在时才将数据播种到数据库中。

如果您想要有效的播种方式,因为您必须播种大量数据,您将获得更好的结果:

public partial class SomeMigration : DbMigration
{
    public override void Up()
    {
        ...
        Sql("UPDATE ...");
        Sql("INSERT ...");
    }

    public override void Down()
    {
        ...
    }
}
于 2012-02-18T19:08:46.883 回答
33

我不建议Sql()在您的方法中使用调用,Up()因为(IMO)这实际上适用于没有内置函数的实际迁移代码,而不是种子代码。

我喜欢将种子数据视为将来可能会改变的东西(即使我的模式没有改变),所以我只是围绕我在种子函数中的所有插入编写“防御性”检查,以确保操作没有触发之前。

考虑一个场景,您有一个以 3 个条目开始的“类型”表,但随后您添加了第 4 个条目。您不需要“迁移”来解决这个问题。

Using还为您提供了一个完整的上下文来使用,这比在Ladislav 演示Seed()的方法中使用纯 sql 字符串要好得多。Sql()

此外,请记住,对迁移代码和种子代码使用内置 EF 方法的好处是您的数据库操作保持平台中立。这意味着您的架构更改和查询能够在 Oracle、Postgre 等上运行。如果您编写实际的原始 SQL,那么您可能会不必要地锁定自己。

您可能不太关心这一点,因为 90% 的使用 EF 的人只会访问 SQL Server,但我只是将它扔在那里,让您对解决方案有不同的看法。

于 2012-05-31T03:05:22.650 回答