.Net Core 2.1, кажется, игнорирует modelBuilder.Entity <TEntity>(). HasData - PullRequest
0 голосов
/ 31 января 2019

У меня есть основной проект .net, который содержит проекты моделей, сервисов и API.Моя первоначальная цель в этом проекте состояла в том, чтобы сделать перечисления более «кодированными».Я хотел просто иметь возможность изменить enum и соответственно обновить базу данных и таблицу поиска.Потратив слишком много времени, пытаясь понять, как это сделать, я решил, что согласен создать специальный класс enum и вручную заполнить его с помощью «HasData».Я делал это раньше и у меня не было проблем с этим.Последний проект, в котором я сделал это, был .Net Core 2.1.Этот проект использует 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; }

}

Он имеет Enum:

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 я загружаю данные, которые я хочу видеть в этой таблице.Поскольку сервисный проект не может быть запущен напрямую и не может узнать его строку подключения, я создал 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;
    }
}

Когда я запускаю 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» создания никогда не бывает там, независимо от того, что я делаю.Я попытался переключить контекст БД на просто старый DbContext.Я попытался изменить порядок событий, сначала добавив таблицу сотрудников, а затем вернувшись назад и добавив таблицу отделов в качестве второй миграции.Похоже, что я ничего не сделаю, чтобы миграция содержала заполненные данные.

Может кто-нибудь определить мою проблему?

1 Ответ

0 голосов
/ 31 января 2019

Следует обратить внимание на предупреждения компилятора.

Здесь

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, который ничего не делает).

...