EF Core使用心得
1、EF默认使用级联删除 DeleteBehavior.Cascade
2、因为abp默认的对数据库操作方法是异步的原因,即使是在数据库操作方法后进行的对model的修改都会在执行数据库操作方法之前完成,并将修改后的数据执行数据库操作方法,因此产生了“内部请求发生错误”的报错,因此最好只对dto进行修改,这样并不会影响到输入数据库的数据。
3、对同一个表有多个外键的情况,要将[ForeignKey("Unit")]放到ID上,且Unit对象是virtual的,如果Foreign对象放到Unit上,则会报错。
4、ef的实体引用跨模块的别的聚合根实体,会报错“The property 'ExtraProperties' could not be mapped”,需要在引用的实体上方增加[NotMapped]属性。但是被加了NotMapped属性的字段不能使用Include()方法。可以使用
5、repository.getdbcontext()和repository.getdbset()后可以使用reference和collection这两个方法。reference查外键引用的对象,collection查聚合的List。需要在Service中使用。
public async Task TestMethod(Guid id)
{
ProductionDbContext productionDbContext= (ProductionDbContext)Repository.GetDbContext();
var manufacture = await GetEntityByIdAsync(id);
productionDbContext.Entry<Manufacture>(manufacture).Collection(c => c.Machines);
DbSet<Manufacture> manufactures = Repository.GetDbSet();//productionDbContext.Manufacture;
}
6、EF会自动追踪查询出来的数据,如果对数据中的导航属性进行赋值,EF则视为插入一条对应数据,如果这个数据已经存在,则报错不能插入重复值。通常出现在主表含有子表List的情况下,一起修改时会发生,很难解决,目前的办法是主表和子表尽量分开修改,不对导航属性赋值,只对model转换后的dto赋值。
7、Ef 、List、 lamda 的动态排序分页
8、如果设置了必填,就不能设置默认值,否则会报错必填值不能为空。因为EF自动生成的插入语句中会减掉有默认值的字段,交给数据库填入默认值。
9、扩展的包EFCore.BulkExtensions
使用bulkUpdate和bulkInsert等方法放到一个service方法中时,其中一个出错,其他对数据库的操作皆会回滚。
10、在同一个service方法中调用不同service的方法操作数据库,其中一个抛出错误则所有操作回滚。
https://docs.abp.io/en/abp/latest/Unit-Of-Work
11、
在仓储层中跨模块调用DbContext或者实体,需要先注册
这样EF才能知道调用的Employee对应的table名称是什么。
12、在DictApplicationAutoMapperProfile中配置
CreateMap<MaterialCompany, MaterialCompanyChange>()
.ForMember(desc => desc.Id, opt => opt.MapFrom(src => Guid.NewGuid()));
这样的代码的时候,由于实体继承 FullAuditedEntity<Guid>,则Id是protected set;
执行语句
model = ObjectMapper.Map<MaterialCompany, MaterialCompanyChange>(materialCompany)
的时候发现modeld的Id没有发生变化,配置没有生效。
原因:由于MaterialCompanyChange类有构造函数
public MaterialCompanyChange(Guid id) : base(id){}
因此无法进行Id的重设,更深原因有待研究。
13、ef的自动提交
用ef查询出的结果如果没有设置AsNoTracking()是默认追踪的,当对追踪实体进行修改,比如赋值。
即使你没有做出提交的操作,比如SaveChangeAsync()。
也会在执行完方法后自动提交修改结果到数据库中去。
14、查询异常报错
[ERR] The association between entity types 'Employee' and 'ExceptionRecord' has been severed, but the relationship is either marked as required or is implicitly required because the foreign key is not nullable. If the dependent/child entity should be deleted when a required relationship is severed, configure the relationship to use cascade deletes. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the key values.
初步推测是由于有多条数据重复引用了同一employee表的同一数据,ef查询语句增加AsNoTracking()方法即可。
15、关于EF Core继承基类
已有Material实体,新建MaterialChange实体继承Material,同时MaterialChange表增加一些额外的字段,同时要求包含Material表里所有的字段。
在DbContextModelCreatingExtension文件中对每个字段都进行配置。
builder.Entity<MaterialChange>(b =>
{
b.ToTable(DictConsts.DbTablePrefix + "MaterialChange", DictConsts.DbSchema).HasComment("模具物料变更").HasBaseType((Type)null);
b.ConfigureByConvention();
……
}
关键一定要加上HasBaseType((Type)null)才能在迁移的时候,把Material基类的字段也添加到MaterialChange表中。