Closed easy999000 closed 1 month ago
ConsoleApp1.zip 测试代码,可以复现.
参考测试, 尽量提供开箱即用最小复现代码, 节省时间
关于可空的问题
经过不断的排除,终于定位具体的bug点位. 当freesql的.Aop.AuditValue.事件挂上一个监控事件后.哪怕是挂一个空方法.都会导致.实体null的字段对比失败. 下面附上,测试代码. 只要.Aop.AuditValue事件有赋值,仓储功能变不能正确对比null字段. 但是奇怪的事情是,2个独立的freesql实体, 既然会互相影响. 这部分代码也在下面的复现代码里面.
在AuditValue 逻辑中
如果遇到了设置了 IsNullable = false
的逻辑,如果数据是null,会主动更新成“”,这样可以避免NULL值数据无法插入的问题
但使用仓储的基于变化的Attach,会把NULL改成“”,会把数据更新成"",原数据库中的值会被清空。
[JsonProperty, Column(StringLength = 100, IsNullable = false)]
public string? Code { get; set; }
var t1 = new ProjectItem { ID = 53, MaxQuantity = 0};
var repo2 = fsql2.GetRepository<ProjectItem>();
repo2.Attach(t1);
t1.MaxQuantity = 111;
var n2 = repo2.Update(t1);
生成的SQL是
UPDATE "ProjectItem" SET "Code" = @p_0, "MaxQuantity" = @p_1, "Name" = @p_2 WHERE ("ID" = 53)
基于仓储的Attach,正确的SQL应该是
UPDATE "ProjectItem" SET "MaxQuantity" = @p_1 WHERE ("ID" = 53)
只要这段代码,更新超过1个字段,那就是bug 我的意图很明显,code的值前后是一致的,没有改变 不需要更新. 但是现在会把code给清空. 内部代码不了解,但是现在发现和 .Aop.AuditValue的事件.有关系.
在AuditValue 逻辑中
如果遇到了设置了
IsNullable = false
的逻辑,如果数据是null,会主动更新成“”,这样可以避免NULL值数据无法插入的问题但使用仓储的基于变化的Attach,会把NULL改成“”,会把数据更新成"",原数据库中的值会被清空。
[JsonProperty, Column(StringLength = 100, IsNullable = false)] public string? Code { get; set; }
var t1 = new ProjectItem { ID = 53, MaxQuantity = 0}; var repo2 = fsql2.GetRepository<ProjectItem>(); repo2.Attach(t1); t1.MaxQuantity = 111; var n2 = repo2.Update(t1);
生成的SQL是
UPDATE "ProjectItem" SET "Code" = @p_0, "MaxQuantity" = @p_1, "Name" = @p_2 WHERE ("ID" = 53)
基于仓储的Attach,正确的SQL应该是
UPDATE "ProjectItem" SET "MaxQuantity" = @p_1 WHERE ("ID" = 53)
有道理.
问题描述及重现代码:
重大BUG
今天我在使用仓储功能进行,统计数值的更新的时候, 发现数据内部的全部字符串字段被清空, 相当于删库跑路了.
我的操作流程是,先从数据库里面把统计数据查询出来,
然后循环把这个要更新的数据源,附加到仓储模块的缓存中(Attach).
在缓存之前,把统计字段(MaxQuantity)设置成0.缓存完成后,再给改回来. 这样这个要更新的数据源和仓储模块中的缓存.应该只有这一个统计字段(MaxQuantity)的值是不一样的.当然只会更新这一个字段的值.
但是我操作完成之后,发现数据库对应的整条数据,文字内容全被清空了.
经过调试我发现,数据源,的被清空的字段,全是null. 但是正常对比字段值是否变化,前后是一样的,应该不会造成数据库值被清空的问题.
我分析的原因是. 数据库的字段,和对应的实体字符串属性是非空类型. [JsonProperty, Column(StringLength = 100, IsNullable = false)]. 但是我手动做这个待更新实体的时候,并没有给所有的字段赋值,我只赋值了,我需要用到的2个字段.id和MaxQuantity. 那么这就导致其他字段在数据源中的值是null. 正常来说这样也不会有问题.
但是,当我把数据attach到仓储层后, 仓储层把原始数据 也就是null的值保留了下来. 但是当我更新数据的时候,执行.repo.Update 的时候,在update的过程中, 数据源中的null值,被修改成了 "",空字符串. 这就导致,对比数据字段变化的时候. 所有的null值的字段都发生了变化,就导致了异常数据的覆盖.
数据库实体
数据库操作方法,也就是这个方法导致的数据被覆盖.
图片传不上来,都发在群里了.
数据库版本
mysql 8
安装的Nuget包
.net framework/. net core? 及具体版本