EntityFramworkCore 配置种子数据(seeding data)

目录

1.准备工作

1.1员工类

1.2 安装EFcore包以及mysql包

1.3 配置mysql数据库

 2.配置种子数据

2.1.简单办法

2.2 保持干净 

2.3 高级一点的做法

2.4 为了部署,自动迁移



1.准备工作

1.1员工类

假设你有一个员工类Employee,如下:

 public class Employee
    {
        public int EmployeeID { get; set; }
        public string Name { get; set; }
        public string Gender { get; set; }
        public int? Salary { get; set; }
        public string Dept { get; set; }

    }

1.2 安装EFcore包以及mysql包

并想固化这个员工数据,通常用EFcore是最自然的想法,直接引入三个nuget包:

 

这里打算使用本地的mysql数据库。

1.3 配置mysql数据库

将数据库连接信息写到appsetting文件中:(注意:根据自己的数据库配置填写ConnectionStrings

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings":  { "MysqlConnection": "server=localhost; port=3306;database=EFStudy;user=root;password=123456;Connect Timeout=300" } 
}

有了数据库配置就可以添加数据库服务,但是因为我们使用的是EFcore,需要添加数据库上下文环境,也就是DbContex,因此,首先要构建这样一个类:

    public class EmployeeDbContext:DbContext
    {
        public DbSet<Employee> Employees { get; set; }
        public EmployeeDbContext(DbContextOptions<EmployeeDbContext> options) : base(options) { }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //待编辑
        }

    }

这样我们就可以为这个数据库环境添加服务:

var connectionString= builder.Configuration.GetConnectionString("MysqlConnection");
builder.Services.AddDbContext<EmployeeDbContext>(options =>

    options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))
);

分别使用:Add-Migration 和Update-Migration命令,创建映射,和创建数据库:

https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=vs忘记了的参考官方页面

如果成功的话,打开你的数据库,就可以看到新建的表:

空空如也。所以问题来了,可能一个公司一开始就是有员工的,你当然可以后续一个一个添加,也可以也sql脚本批量添加,这里用代码的办法来添加,所以终于要引出本文的主题了。


 2.配置种子数据

2.1.简单办法

前面在编写EmployeeDbContext的时候,有个函数是空的,没错,就是下面这个函数:

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

        }

我们可以直接在这个函数中添加种子数据,办法很简单:


        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Employee>().HasData(
                new Employee() { Name = "Pranaya", Gender = "Male", Salary = 10000, Dept = "IT" ,EmployeeID=1},
                new Employee() { Name = "张三", Gender = "Male", Salary = 100, Dept = "Saler",EmployeeID=2 },
                new Employee() { Name = "东方不败", Gender = "Unknow", Salary = 100000, Dept = "Leader",EmployeeID=3 });
        }
        

添加了数据要重新迁移,以及更新数据库:

Now we can create a new migration:

PM> Add-Migration SeedInitialData

And apply it:

PM> Update-Database

现在去数据库看,就有数据了:

2.2 保持干净 

如果种子数据比较多,那么势必为塞满当前EmployeeDbContext,既不美观,也不符合Code Clean原则:

我们可以使用扩展函数:

namespace RepositoryPatternStudy.Extensions
{
    public static  class EFExtension
    {
        public static void AddSeed(this ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Employee>().HasData(
                new Employee() { Name = "Pranaya", Gender = "Male", Salary = 10000, Dept = "IT", EmployeeID = 1 },
                new Employee() { Name = "张三", Gender = "Male", Salary = 100, Dept = "Saler", EmployeeID = 2 },
                new Employee() { Name = "东方不败", Gender = "Unknow", Salary = 100000, Dept = "Leader", EmployeeID = 3 }
                );
                
        }
    }
}

那么原函数就可以写成一行:

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.AddSeed();
            //modelBuilder.Entity<Employee>().HasData(
            //    new Employee() { Name = "Pranaya", Gender = "Male", Salary = 10000, Dept = "IT" ,EmployeeID=1},
            //    new Employee() { Name = "张三", Gender = "Male", Salary = 100, Dept = "Saler",EmployeeID=2 },
            //    new Employee() { Name = "东方不败", Gender = "Unknow", Salary = 100000, Dept = "Leader",EmployeeID=3 });
        }

重新迁移更新一遍,你会发现效果一样。

2.3 高级一点的做法

如果我们的项目有很多表也有很多初始数据,那么我们的表将变得难以阅读和维护。EFcore提供了一个接口:IEntityTypeConfiguration<T>,使用这个接口,我们可以为不同的实体编写单独的配置类。具体操作如下:

构建一个派生与此接口的配置类:

    public class EmployeeConfiguration : IEntityTypeConfiguration<Employee>
    {
        public void Configure(EntityTypeBuilder<Employee> builder)
        {
            builder.ToTable("NewEmployee");
            builder.Property(s => s.Name)
                .IsRequired(false);
            builder.Property(s => s.Name)
                .HasDefaultValue(true);
            builder.HasData(
                new Employee() { Name = "Pranaya", Gender = "Male", Salary = 10000, Dept = "IT", EmployeeID = 1 },
                new Employee() { Name = "张三", Gender = "Male", Salary = 100, Dept = "Saler", EmployeeID = 2 },
                new Employee() { Name = "东方不败", Gender = "Unknow", Salary = 100000, Dept = "Leader", EmployeeID = 3 }
                );
        }
    }

实际上在Configure中不仅可以配置种子数据,还是配置其它内容:

有了这个配置类之后,我们就可以家在到OnModelCreating类中:

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.ApplyConfiguration(new EmployeeConfiguration());

           // modelBuilder.AddSeed();
            //modelBuilder.Entity<Employee>().HasData(
            //    new Employee() { Name = "Pranaya", Gender = "Male", Salary = 10000, Dept = "IT" ,EmployeeID=1},
            //    new Employee() { Name = "张三", Gender = "Male", Salary = 100, Dept = "Saler",EmployeeID=2 },
            //    new Employee() { Name = "东方不败", Gender = "Unknow", Salary = 100000, Dept = "Leader",EmployeeID=3 });
        }

重新,迁移一遍,更新后,你会发现你的表名变为:NewEmployee,且数据都在。

2.4 为了部署,自动迁移

到此为止,种子数据的设置就告一段落了,但是有一个实际问题需要解决,如果我们的服务要部署到服务器,我们可能首先要在服务器手动进行迁移,也就是运行前面两条命令。当每隔服务都有数据库时,这会显得很繁琐,所以我们希望能够在运行时,自动迁移。

首先我们创建一个静态类,因为我们要添加扩展方法:

    public static class MigrationManager
    {
    }

我们往刚才的类加静态方法:

 public static IHost MigrationDatabase(this IHost host)
        {
            using var scope = host.Services.CreateScope();
            var service = scope.ServiceProvider;
            using var appContext = scope.ServiceProvider.GetRequiredService<EmployeeDbContext>();
            try
            {
                appContext.Database.Migrate();
            }
            catch (Exception ex)
            {
                var logger = service.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occured seeding the DB");
            }
            return host;
        }

然后在配置中使用:

var app = builder.Build();

app.MigrationDatabase();

现在,你删掉数据库中的 _EFMigrationsHistory 以及Employee表,重新运行项目,你会发现之前的配置,会自动迁移,种子数据也在表里了。


数据库的配置弄完之后,接下来就是数据仓储了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值