使用EF Core 7无法将SQL Server数据库decimal字段设为0的问题
问题原因与解决方案
核心原因
你用Attach方法将新创建的TransactionClass实体附加到上下文时,该实体的Percentage字段默认值是0(decimal类型的默认值就是0,代码里的= default!实际等价于0)。之后你把它设置为0,EF Core的变更追踪系统会判定这个字段的值没有发生变化,因此不会生成更新该字段的SQL语句,数据库里的值自然不会被修改。
而当你设置大于0的值时,因为初始默认值是0,新值和初始值存在差异,变更追踪能检测到变化,所以会正常生成更新语句。
解决方法
有三种可行的解决方式:
方法1:手动标记字段为已修改
在设置Percentage的值后,显式告知EF Core该字段已修改,强制生成更新语句:
public bool UpdateClasses(Accounting.Shared.Dtos.Request.Transaction.Class.UpdateDto transactionClass) { using (accountingContext db = new()) { var updateClass = new TransactionClass { TransactionClassId = transactionClass.TransactionClassId }; db.TransactionClasses.Attach(updateClass); updateClass.Name = transactionClass.Name; updateClass.Percentage = 0; // 手动标记字段为已修改 db.Entry(updateClass).Property(x => x.Percentage).IsModified = true; db.SaveChanges(); } return true; }
方法2:先查询实体再修改
如果业务场景允许,先从数据库加载目标实体,再修改字段值,这样EF Core能准确追踪到值的变化:
public bool UpdateClasses(Accounting.Shared.Dtos.Request.Transaction.Class.UpdateDto transactionClass) { using (accountingContext db = new()) { var updateClass = db.TransactionClasses.FirstOrDefault(x => x.TransactionClassId == transactionClass.TransactionClassId); if (updateClass != null) { updateClass.Name = transactionClass.Name; updateClass.Percentage = 0; db.SaveChanges(); } } return true; }
方法3:调整实体默认值(不推荐)
把实体中Percentage的默认值改成非0数值,比如:
public decimal Percentage { get; set; } = -1;
但这种方法会引入逻辑混淆,只有在特殊场景下才考虑使用,优先选择前两种方法。
补充说明
Name字段能正常更新,是因为实体初始化时Name为String.Empty,而你设置的是传入的transactionClass.Name(通常不是空字符串),变更追踪能检测到这个差异,所以会生成更新语句。- 数据库的默认值仅在插入新记录时生效,更新操作不会自动调用默认值,必须显式处理更新逻辑。
内容的提问来源于stack exchange,提问作者Musaffar Patel
相关产品推荐
相关产品推荐

