Entity Framework:ValueGeneratedOnUpdate新增触发问题及仅更新赋值问询
问题描述
原本期望使用ValueGeneratedOnUpdate时,仅当实体已存在(执行更新操作)时才调用指定的值生成器,但实际发现该值在新增实体时也会被生成。
相关代码
属性配置代码
builder.Property(self => self.CreatedAt) .ValueGeneratedOnAdd() .HasValueGenerator<UtcTimeValueGenerator>(); builder.Property(self => self.UpdatedAt) .ValueGeneratedOnUpdate() .HasDefaultValue(null) .HasValueGenerator<UtcTimeValueGenerator>();
种子数据代码
builder.HasData(new List<Device> { new Device { Id = 1, ParkingLotId = 1, Serial = "test", SigfoxSerial = "test" } });
自定义值生成器代码
public class UtcTimeValueGenerator : ValueGenerator<DateTime> { public override bool GeneratesTemporaryValues => false; public override DateTime Next(EntityEntry entry) => DateTime.UtcNow; }
请问仅通过IEntityTypeConfiguration,能否实现仅当实体已存在时为特定列设置datetime属性?
解答
仅通过IEntityTypeConfiguration的纯配置项无法实现该需求——ValueGeneratedOnUpdate结合HasValueGenerator的默认逻辑中,EF Core不会自动过滤新增实体的调用。但可以通过在值生成器内部判断实体状态来达成目标,这仍然可以和IEntityTypeConfiguration配合使用,无需额外的业务逻辑。
修改方案
- 调整值生成器逻辑:让它仅在实体处于
Modified状态时生成UTC时间,新增(Added)时返回null,匹配你配置的HasDefaultValue(null):
public class UtcTimeValueGenerator : ValueGenerator<DateTime?> { public override bool GeneratesTemporaryValues => false; public override DateTime? Next(EntityEntry entry) { return entry.State == EntityState.Modified ? DateTime.UtcNow : null; } }
确保属性类型匹配:如果你的
Device类中UpdatedAt是不可空DateTime类型,需改为可空DateTime?,否则新增时无法设置为null,EF Core会强制调用值生成器导致生成时间。保持原有配置不变:你的
IEntityTypeConfiguration配置无需修改,继续沿用即可。
效果验证
- 新增实体时:
UpdatedAt会被设为null,符合预期; - 更新实体时:值生成器触发,生成当前UTC时间;
- 种子数据导入时:
UpdatedAt保持为null,与默认值配置一致。
内容的提问来源于stack exchange,提问作者user21157784
相关产品推荐
相关产品推荐

