首页 > 解决方案 > 如何在实体框架配置中播种动态数据

问题描述

我有以下用于播种数据的扩展方法:

public static class ModelBuilderExtensions
{
   public static void Seed(this ModelBuilder modelBuilder)
   {
      //Key is GUID type and automatically generated on insert
      modelBuilder.Entity<Author>().Property(x => x.Key).HasDefaultValueSql("NEWID()"); 

      modelBuilder.Entity<Author>().HasData(
        new Author
        {
            FirstName = "William",
            LastName = "Shakespeare"
        });   
    }
  }

现在,生成的键应作为值传递给其他表种子数据。

我如何获得AuthorId以下陈述?

   modelBuilder.Entity<Book>().HasData(
        new Book { BookId = 1, AuthorId = ?, Title = "Hamlet" },
        new Book { BookId = 2, AuthorId = ?, Title = "King Lear" },
        new Book { BookId = 3, AuthorId = ?, Title = "Othello" }
    );

标签: c#sqlentity-framework

解决方案


HasData启用IDENTITY_INSERT. 我已经检查过它调试DataSeeding项目:

dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
      IF EXISTS (SELECT * FROM [sys].[identity_columns] 
     WHERE [name] IN (N'BlogId', N'Url') AND 
           [object_id] = OBJECT_ID(N'[Blogs]'))
          SET IDENTITY_INSERT [Blogs] ON;       #<--- here
      INSERT INTO [Blogs] ([BlogId], [Url])

      VALUES (1, N'http://sample.com');

      IF EXISTS (SELECT * FROM [sys].[identity_columns] 
                 WHERE [name] IN (N'BlogId', N'Url') AND 
                       [object_id] = OBJECT_ID(N'[Blogs]'))
          SET IDENTITY_INSERT [Blogs] OFF;      #<--- here

然后,对于您的数据,简单的方法是通知 PK:

  modelBuilder.Entity<Author>().HasData(
    new Author
    {   Id = 1,     //#<--- here
        FirstName = "William",
        LastName = "Shakespeare"
    });  

  ...

  modelBuilder.Entity<Book>().HasData(
    new Book { BookId = 1, AuthorId = 1, #<--- here
               Title = "Hamlet" }, 

引用数据播种文档

即使通常由数据库生成,也需要指定主键值。它将用于检测迁移之间的数据更改。


推荐阅读