日志中发现下面的 EF Core 告警:
The 'bool' property '"IsDeleted"' on entity type '"EntityA"' is configured with a database-generated default. This default will always be used for inserts when the property has the value 'false', since this is the CLR default for the 'bool' type. Consider using the nullable 'bool?' type instead, so that the default will only be used for inserts when the property value is 'null'.
The 'bool' property '"IsActive"' on entity type '"EntityB"' is configured with a database-generated default. This default will always be used for inserts when the property has the value 'false', since this is the CLR default for the 'bool' type. Consider using the nullable 'bool?' type instead, so that the default will only be used for inserts when the property value is 'null'.
EntityA 的属性定义
public bool IsDeleted { get; set; }
EF Core Map 定义
builder.Property(p => p.IsDeleted).HasDefaultValueSql("0");
EntityB 的属性定义
public bool IsActive { get; set; } = true;
EF Core Map 定义
builder.Property(x => x.IsActive).HasDefaultValue(true);
对于 EntityA,用 HasDefaultValue(false)
取代 HasDefaultValueSql("0")
可以解决
builder.Property(p => p.IsDeleted).HasDefaultValue(false);
生成的 INSERT SQL 语句中没有 IsDeleted
字段,会使用数据库中设置的默认值,符合预期
对于 EntityB,可以通过 Nullable backing fields for bool properties 让生成的 INSERT SQL 语句中没有 IsActive
字段,但 Warning 依然存在,我们选择了移除 .HasDefaultValue(true)
,不使用数据库而使用代码中的默认值。
.NET 8 中的 EF Core 8 通过引入 HasSentinel()
解决了这个问题,详见 Sentinel values and database defaults
builder.Property(x => x.IsActive).HasDefaultValue(true).HasSentinel(true);
github 上的相关 issue https://github.com/dotnet/efcore/issues/12198
– dudu 2年前stackoverflow 上的问题 How to set another value on a boolean with defaut value with Entity Framework Core?
– dudu 2年前stackoverflow 上的相关问题 Issue with EF Core 5 HasDefaultValue, ef pushes default value when value is set to the .Net type default
– dudu 2年前