简体   繁体   English

.Net Core 2.1似乎忽略了modelBuilder.Entity <TEntity> ().HasData

[英].Net Core 2.1 seems to be ignoring modelBuilder.Entity<TEntity>().HasData

I have a .net core project that contains model, service and api projects. 我有一个.net核心项目,其中包含模型,服务和api项目。 My original goal with this project was to make enums work in a more "code-first" way. 我对该项目的最初目标是使枚举以“代码优先”的方式工作。 I wanted to just be able to modify the enum and get the database and the lookup table to be updated accordingly. 我只想能够修改枚举并获取要相应更新的数据库和查找表。 After spending too much time trying to figure out how to do that, I decided I'd settle for creating a special enum class and manually seed it using "HasData". 在花了太多时间试图弄清楚该怎么做之后,我决定创建一个特殊的枚举类,并使用“ HasData”手动将其设置为种子。 I have done this before and have not had problems with it. 我以前做过,但没有遇到任何问题。 The last project I did this in was .Net Core 2.1. 我在其中进行的最后一个项目是.Net Core 2.1。 This project is using 2.2. 项目正在使用2.2。 I can't tell if I've discovered a weird bug or if I'm just doing something wrong. 我不知道我是否发现了一个奇怪的错误,或者我只是做错了什么。 My "services" project is where the DbContext lives and most of the pertinent code is. 我的“服务”项目是DbContext所在的地方,并且大多数相关代码都在其中。

I have a model that looks like: 我有一个看起来像的模型:

public class Employee : IEmployee
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Display(Name = "Id")]
    public int Id { get; set; }

    [StringLength(512, ErrorMessage = "The first name cannot be longer than 512 characters")]
    [Display(Name = "First Name")]
    [Required]
    public string FirstName { get; set; }

    [StringLength(512, ErrorMessage = "The last name cannot be longer than 512 characters")]
    [Display(Name = "Last Name")]
    [Required]
    public string LastName { get; set; }

    public Department Department { get; set; }

}

It has an Enum: 它有一个枚举:

public enum Department{

    [Description("Sales")]
    Sales = 1,

    [Description("Customer Service")]
    CustomerService = 2,

    [Description("Technical Support")]
    TechnicalSupport = 3
}

I created a model that corresponds to the enum that looks like this: 我创建了一个对应于如下枚举的模型:

[Table("Department")]
public class DepartmentEnum : EnumBase<Department>
{
    public DepartmentEnum()
    {
    }
}

It has a base class that looks like this: 它具有一个基类,如下所示:

public class EnumBase<TEnum> where TEnum : struct
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public virtual int Id { get; set; }

    [Required]
    [MaxLength(100)]
    public virtual string Name { get; set; }

    [MaxLength(100)]
    public virtual string Description { get; set; }

    public virtual bool Deleted { get; set; } = false;
}

I created a DbContext that looks like this: 我创建了一个DbContext,如下所示:

public class ApplicationDbContext : IdentityDbContext<AppUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options){}

    public DbSet<Employee> Employees { get; set; }

    public DbSet<DepartmentEnum> Departments { get; set; }

    protected internal virtual void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<DepartmentEnum>().HasData(
            new DepartmentEnum { Id = 1, Name = "Sales", Description = "Sales", Deleted = false },
            new DepartmentEnum { Id = 2, Name = "Customer Service", Description = "Customer Service", Deleted = false },
            new DepartmentEnum { Id = 3, Name = "TechnicalSupport", Description = "Technical Support", Deleted = false }
        );

    }
}

In the OnModelCreating section I am seeding the data that I want to be in this table. OnModelCreating部分中,我将OnModelCreating要放在此表中的数据。 Because the service project can't be launched directly and can't learn it's connection string I created a DbContextFactory that inherits from IDesignTimeDbContextFactory<ApplicationDbContext> it looks like this: 因为该服务项目无法直接启动并且无法了解它的连接字符串,所以我创建了一个DbContextFactory ,它继承自IDesignTimeDbContextFactory<ApplicationDbContext>它看起来像这样:

public class DbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
{
    public ApplicationDbContext CreateDbContext(string[] args)
    {
        //uncomment this line if you need to debug this code
        //then choose yes and create a new instance of visual
        //studio to step through the code
        //Debugger.Launch();

        var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
        builder
            .UseSqlServer(@"Server=(localdb)\MSSQLLocalDB;Database=EnumSeeder;Trusted_Connection=True;MultipleActiveResultSets=true");

        //get the dbContext
        var context = new ApplicationDbContext(builder.Options);

        return context;
    }
}

When I run add-migration InitialCreate I am expecting to see my model data reflected in the migration file. 当我运行add-migration InitialCreate我期望看到我的模型数据反映在迁移文件中。 When I look at the department table all I see is: 当查看部门表时,我看到的是:

migrationBuilder.CreateTable(
    name: "Department",
    columns: table => new
    {
        Id = table.Column<int>(nullable: false)
            .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
        Name = table.Column<string>(maxLength: 100, nullable: false),
        Description = table.Column<string>(maxLength: 100, nullable: true),
        Deleted = table.Column<bool>(nullable: false)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Department", x => x.Id);
    });

The "HasData" potion of the creation is never there no matter what I do. 无论我做什么,创建的“ HasData”部分永远都不会存在。 I have tried switching the db context to just plain old DbContext . 我尝试将db上下文切换为普通的旧DbContext I have tried changing the order of events by adding the employee table first and then going back and adding the department table as a second migration. 我尝试通过先添加雇员表然后再返回并添加部门表作为第二次迁移来更改事件的顺序。 It seems like nothing I do will get the migration to contain the seeded data. 看来我什么也做不了,将无法迁移包含种子数据的数据。

Can anyone spot my problem? 谁能发现我的问题?

You should pay attention to compiler warnings. 您应注意编译器警告。

Here 这里

protected internal virtual void OnModelCreating(ModelBuilder modelBuilder)

you are shadowing the base OnModelCreating method (there must be a compiler warning telling that). 您正在遮盖基本的OnModelCreating方法(必须有一个编译器警告告诉您)。 And of course EF Core infrastructure is not calling your method, but the one defined in DbContext class. 当然,EF Core基础结构不是在调用您的方法,而是在DbContext类中定义的方法。

Hence whatever you put there has no effect - the Department table is created based on EF Core conventions, and of course no data seed. 因此,无论您放置在那里什么都没有作用Department表是基于EF Core约定创建的,当然也没有数据种子。

Change the method signature to 将方法签名更改为

protected override void OnModelCreating(ModelBuilder modelBuilder)

and make sure to call 并确保致电

base.OnModelCreating(modelBuilder);

at the very beginning. 一开始 This is especially important when you inherit IdentityContext (or any base context class other than the DbContext which does nothing). 当您继承IdentityContext (或除DbContext不执行任何操作的任何基本上下文类)时,这一点尤其重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM