我有一个.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
部分中,我播种了要在此表中存储的数据。由于该服务项目无法直接启动并且无法了解其连接字符串,因此我创建了一个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
。我尝试通过先添加雇员表然后再返回并添加部门表作为第二次迁移来更改事件的顺序。看来我什么也做不了,迁移将不包含种子数据。
有人可以发现我的问题吗?
答案 0 :(得分:3)
您应该注意编译器警告。
这里
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
以外不执行任何操作的任何基本上下文类)时,这尤其重要。