EF Core 5.0结合ABP+Sqlite时重写带初始化器属性值加载异常问题
问题成因
- EF Core默认对带有初始化器的重写属性,采用
PreferField的访问策略,实例化实体时会优先执行属性初始化器赋值,变更跟踪器容易将初始化器设置的值判定为用户显式赋值,不会用数据库读取到的值进行覆盖。 - 你在类A中重写了基类的
Category和SubCategory属性并添加了初始化器,EF Core的模型绑定/变更跟踪没有正确捕获你对SubCategory的手动赋值,部分场景下插入数据库时实际写入的是初始化器的默认值甚至空值,查询时自然无法得到期望的自定义值。 - 类B没有重写属性也没有添加初始化器,EF Core的映射逻辑完全正常,因此测试可以通过。
最优解决方案
不需要放弃属性初始化器,也不需要额外引入工厂模式,通过EF Core原生配置即可满足需求:
在你的DbContext的OnModelCreating方法中,对类A的重写属性显式配置访问模式,强制EF Core优先使用数据库值覆盖初始化器的默认值,同时保留插入时的自定义值捕获逻辑:
protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<A>(entity => { // 强制读写属性时跳过字段优先逻辑,直接操作属性值 entity.Property(p => p.Category) .UsePropertyAccessMode(PropertyAccessMode.PreferProperty) .HasDefaultValue("CategoryA"); // 和初始化器默认值保持一致,兼容未赋值的插入场景 entity.Property(p => p.SubCategory) .UsePropertyAccessMode(PropertyAccessMode.PreferProperty) .HasDefaultValue("Other"); }); }
配置完成后,你手动new类A的实例时依然会拿到SubCategory的默认值Other,插入数据库时自定义赋值会被正常写入,查询时数据库存储的值会直接覆盖初始化器的默认值,测试用例可正常通过。
备选方案
如果不想修改EF Core配置,也可以通过拆分构造函数实现需求:
public class A : Base { // 专供EF Core实例化使用的私有构造函数,不会执行默认值赋值逻辑 private A() { } // 业务代码实例化时调用的公共构造函数,会设置默认值 public A() { Category = "CategoryA"; SubCategory = "Other"; } public override string Category { get; set; } public override string SubCategory { get; set; } }
该方案不需要修改EF Core配置,EF Core实例化实体时会调用私有构造函数,直接使用数据库读取到的属性值,业务代码new实例时依然保留默认值。
内容的提问来源于stack exchange,提问作者Phija
相关产品推荐
相关产品推荐

