这一小节的内容主要是关于EFCore的种子数据。
EFCore中添加种子数据
在DbContext中添加如下测试代码:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
#region Configuration
modelBuilder.Entity()
.HasKey(x => new { x.CityId, x.CompanyId });
modelBuilder.Entity()
.HasOne(x => x.Province).WithMany(x => x.Cities).HasForeignKey(x => x.ProvinceId);
modelBuilder.Entity()
.HasOne(x => x.City).WithMany(x => x.CityCompanies).HasForeignKey(x => x.CityId);
modelBuilder.Entity()
.HasOne(x => x.Company).WithMany(x => x.CityCompanies).HasForeignKey(x => x.CompanyId);
modelBuilder.Entity()
.HasOne(x => x.City).WithOne(x => x.Mayor).HasForeignKey(x => x.CityId);
#endregion
modelBuilder.Entity().HasData(
new Province
{
Id = 1,
Name="广东",
Population = 90000000
});
}
需要注意,EFCore添加种子数据时,主键Id是一定要添加的,不然会报错。
EFCore在执行插入这条数据的过程中,会自动先开启主键插入功能,插入完成后再关闭主键插入功能。
EFCore修改种子数据
在当前这种情况下,如果在不改变Id的前提下修改种子数据的话,生成的SQL脚本就变成Update。
如果修改数据的时候连Id也改了的话。查看生成的SQL脚本,会先删除之前的插入的一笔种子数据,然后再插入现在这一笔数据。
EFCore添加关联种子数据
添加种子数据的时候一同添加关联的数据,例如添加province的时候添加city数据。这个时候City单独添加,并且要指定外键。
modelBuilder.Entity().HasData(
new Province
{
Id = 13,
Name="江苏",
Population = 90333887,
Cities = new List
{
new City(){Id = 1301,Name = "苏州"},
new City(){Id = 1302,Name = "南京"},
new City(){Id = 1303,Name = "连云港"},
}
});
要避免这个错误,EFCore种子数据中添加关联数据可以这么写:
modelBuilder.Entity().HasData(
new Province
{
Id = 13,
Name="江苏",
Population = 90333887,
});
modelBuilder.Entity().HasData(
new City {ProvinceId = 13,Id = 1301, Name = "苏州"},
new City { ProvinceId = 13, Id = 1302, Name = "南京"},
new City { ProvinceId = 13, Id = 1303, Name = "连云港"}
);
如果代码中没有明确的外键,例如City中没有ProvinceId
这个外键。那么可以通过匿名类传入的方式,让EF自动构建一个外键。
modelBuilder.Entity().HasData(
new {ProvinceId = 13,Id = 1301, Name = "苏州"},
new { ProvinceId = 13, Id = 1302, Name = "南京"},
new { ProvinceId = 13, Id = 1303, Name = "连云港"}
);
对于Guid外键的情况我们又该怎么处理呢?例如有Student这个类:
public class Student
{
public Guid Id { get; set; }
public string Name { get; set; }
}
那么添加种子数据时,如果按照下列方式去添加的话,会自动生成一个Guid。modelBuilder.Entity<Student>().HasData(
new Student {Id = Guid.NewGuid(), Name = "张三"});
但是,此时一旦对种子数据进行修改,都会重新去生成一个主键,原来的主键就会被自动删除了。例如这里修改张三
为张三2
。
因此,这种情况,需要先定义一个Guid。这样修改种子数据就会执行update方法,而不是先删除后插入的方式。
var studentGuid=new Guid("48fb8670-9f70-4a46-b015-5fd341f32abd");
modelBuilder.Entity().HasData(
new Student {Id = studentGuid, Name = "张三3"});