【问题标题】:.Net Core 2.1 seems to be ignoring modelBuilder.Entity<TEntity>().HasData.Net Core 2.1 似乎忽略了 modelBuilder.Entity<TEntity>().HasData
【发布时间】:2019-01-31 19:35:33
【问题描述】:

我有一个 .net 核心项目,其中包含模型、服务和 api 项目。我对这个项目的最初目标是让枚举以更“代码优先”的方式工作。 我希望能够修改枚举并相应地更新数据库和查找表。在花了太多时间试图弄清楚如何做到这一点之后,我决定我会满足于创建一个特殊的枚举类并使用“HasData”手动播种它。我以前做过这个并且没有遇到任何问题。我做的最后一个项目是 .Net Core 2.1。这个project 使用的是 2.2。我不知道我是否发现了一个奇怪的错误,或者我只是做错了什么。我的“服务”项目是 DbContext 所在的地方,也是大部分相关代码所在的地方。

我有一个看起来像这样的模型:

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; }

}

它有一个枚举:

public enum Department{

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

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

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

我创建了一个与枚举对应的模型,如下所示:

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

它有一个如下所示的基类:

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;
}

我创建了一个如下所示的 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 }
        );

    }
}

OnModelCreating 部分,我正在播种我希望在此表中的数据。因为服务项目无法直接启动,也无法获知它的连接字符串,所以我创建了一个继承自IDesignTimeDbContextFactory&lt;ApplicationDbContext&gt;DbContextFactory,它看起来像这样:

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;
    }
}

当我运行add-migration InitialCreate 时,我希望看到我的模型数据反映在迁移文件中。当我查看部门表时,我看到的是:

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);
    });

无论我做什么,创造的“HasData”药水都不存在。 我尝试将 db 上下文切换为普通的旧 DbContext。我尝试通过首先添加员工表然后返回并添加部门表作为第二次迁移来更改事件顺序。似乎我所做的任何事情都不会让迁移包含种子数据。

谁能发现我的问题?

【问题讨论】:

    标签: c# entity-framework enums .net-core entity-framework-core


    【解决方案1】:

    您应该注意编译器警告。

    这里

    protected internal virtual void OnModelCreating(ModelBuilder modelBuilder)
    

    您正在隐藏基本的OnModelCreating 方法(必须有一个编译器警告来说明这一点)。当然,EF Core 基础架构不会调用您的方法,而是调用DbContext 类中定义的方法。

    因此,您放在那里的任何内容都没有效果 - Department 表是基于 EF Core 约定创建的,当然没有数据种子。

    将方法签名改为

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    

    并确保致电

    base.OnModelCreating(modelBuilder);
    

    在一开始。当您继承 IdentityContext(或除 DbContext 之外的任何基本上下文类,它什么都不做)时,这一点尤其重要。

    【讨论】:

    • 好的,现在我得去拿我的笨蛋帽,坐在角落里 :) 警告就在那里等着我读。它现在就像一个魅力。感谢您的帮助!
    猜你喜欢
    • 2021-10-28
    • 2016-09-30
    • 2016-03-16
    • 2014-02-03
    • 2012-03-11
    • 2013-09-07
    • 2016-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多