【问题标题】:Why is the Seed method called again in my EF code first migrations scenario?为什么在我的 EF 代码优先迁移方案中再次调用 Seed 方法?
【发布时间】:2018-01-02 22:47:09
【问题描述】:

我有一个 EF 代码优先项目,我是如何为数据库播种的

internal sealed class Configuration : DbMigrationsConfiguration<myDB>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
            ContextKey = "myDB.Auth.Service.DAL.myDB";
        }

        protected override void Seed(myDBdb)
        {
           var mProduct = new Product
             {
                Name = "default product",
               CreatedDate = DateTime.Now
            };

           db.Products.AddOrUpdate(mProduct);
           db.SaveChanges();
        }
}

我有一个使用上述代码的 wcf 服务。我意识到,每次我重新启动 wcf 服务(从 Visual Studio 或 IIS)时,都会调用上面的代码。结果,数据库中添加了多个“默认产品”,有人知道为什么会这样吗?

【问题讨论】:

  • 您找到问题的有效答案了吗?

标签: ef-code-first entity-framework-migrations


【解决方案1】:

迁移种子在每个更新数据库之后运行,因此您需要通过测试存在性或使用 AddOrUpdate 使脚本具有幂等性。如果您只想在创建数据库时播种,则有一个单独的上下文种子方法,该方法仅在创建数据库时运行。

https://blog.oneunicorn.com/2013/05/28/database-initializer-and-migrations-seed-methods/

AddOrUpdate for seeding

编辑:

当您使用 MigrateDatabaseToLatestVersion 初始化程序时,您的种子方法会在您的应用程序每次运行时运行。如果您想控制此过程,请将您的初始化程序切换为 null:

Database.SetInitializer(new NullDatabaseInitializer<ApplicationDbContext>());

然后在需要时手动运行迁移。更进一步,您可以编写自己的初始化程序,并在数据库不存在或数据库需要更新时执行您想要的操作:

Database.SetInitializer(new ValidateDbInitializer<ApplicationDbContext>());

// ref: https://coding.abel.nu/2012/03/prevent-ef-migrations-from-creating-or-changing-the-database/
public class ValidateDbInitializer<TContext> : IDatabaseInitializer<TContext>
    where TContext : ApplicationDbContext
{
    public void InitializeDatabase(TContext context)
    {
        if (!context.Database.Exists())
        {
            throw new InvalidOperationException("The database does not exist. Check your server and connection string.");
        }
        if (!context.Database.CompatibleWithModel(true))
        {
            throw new InvalidOperationException("The database is not up to date. You may need to apply update(s).");
        }
    }
}

【讨论】:

  • 嗨,看起来每次我的 wcf 服务重新启动(通过 Visual Studio 或 iis)时,都会调用初始化过程。有没有办法说明这是为什么?
【解决方案2】:

第一步是使用工具菜单,选择库包管理器,然后选择包管理器控制台。在包管理器控制台窗口中输入以下命令。

  Enable-Migrations

这将在您的项目中添加名为 Migrations 的文件夹以及名为 Configuration.cs 的代码文件。

在 Configuration.cs 中键入以下行

使用您的项目名称.Models;

protected override void Seed(yourprojectname.Models.MyServiceContext context)
{
   context.MyDB.AddOrUpdate(x => x.Id,
    new MyData() {  Name = "Mohit",   CreatedDate= "14/05/2016" },
    new MyData() {  Name = "Prabhat", CreatedDate= "15/05/2016" },

    );  
 }

现在输入 Update-Database
在包管理器控制台窗口中

【讨论】:

    【解决方案3】:

    尝试以下方法:

    protected override void Seed(myDBdb)
    {
        var mProduct = new Product
        {
            Id = 1,
            Name = "default product",
            CreatedDate = DateTime.Now
        };
    
        db.Products.AddOrUpdate(mProduct);
        db.SaveChanges();
    }
    

    【讨论】:

      【解决方案4】:

      当您第一次使用应用程序初始化数据时,请使用DropCreateDatabaseAlways。例如:

      public class MyClass : DropCreateDatabaseAlways<connectionstringContextName>
      {
           protected override void Seed(MyContext context)
           {
               // Your seed data
           }
      }
      

      【讨论】:

      • 但数据库已经存在,(我第一次运行代码时,数据库是使用正确的种子数据创建的)。实体框架不应该自动找到吗?
      猜你喜欢
      • 1970-01-01
      • 2016-05-26
      • 1970-01-01
      • 2023-01-30
      • 2012-03-04
      • 1970-01-01
      • 2016-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多