ef使用json类型无法触发更新排查

一.问题背景

 

 

首先诸位请看以上代码,不知道有没有发现什么问题?

3

2

1

 

集成流的配置,目前是使用json结构,保存到数据库中的。当初加这个的时候就有发现,没有写update不更新,但是当初因为一些原因,没有主动去深究这个问题,而是手动补了一行update去触发更新。这几天在调整集成流配置结构的时候,发现了之前写的这个代码,并深究了一下原因。

二.问题定位

 

首先可以来看一下另一段代码,同样的场景,类似的结构,但是上面这段代码可以触发ef的更新,同学们,发动你们聪明的小脑瓜,有没有想到为什么?这里与异常代码的区别是这里的steps重新赋了个值,基于以上现象,我们推测是因为异常代码只是替换了json内部数据,但是没有更改引用类型的引用地址,导致ef的跟踪器没有触发跟踪。基于以上猜测,我们去翻阅到了一些资料

 

 

综上所述,确实是由于我们使用了json类型,导致部分数据的变更,没有触发跟踪器的跟踪,为此,我们补上了以下代码

首先我们实现了了一个值比较器,使用json的md5去校验值是否变更

public class GenericComparer<T> : ValueComparer<T> where T:new()
    {
        public GenericComparer() : base((s, t) => Equal(s, t), CreateDefaultHashCodeExpression(false), c => SnapShot(c))
        {

        }

        public static bool Equal(T? s, T? t)
        {
            if (s == null || t == null)
            {
                return false;
            }
            return s.ToJsonInDb().ToMd5() == t.ToJsonInDb().ToMd5();
        }

        public static T SnapShot(T c)
        {
            if (c is null) { return new(); }
            return c.Adapt<T>();
        }
    }

 

 

然后在数据库上下文配置中加上了以下配置

 

添加了这两段代码之后,ef上下文即可检测到值的变更,进而跟踪数据,生成正确的sql语句。

 

 

await Repository.Respositiy<BAS_FlowConfig>().UpdateAsync(flowConfig);

另外我们再来看看由主动触发更新,生成的ef更新语句,这里的更新是会更新整行数据的所有字段,而正常由ef跟踪形成的sql,是只更新修改过的字段,所以减少主动更新的使用,可以提高一部分性能

 

三.结论

  1. 复杂类型的数据,需要自己定义值比较器,否则引用地址不变,ef无法正确获取值的变更
  2. 主动update会更新整行数据所有字段,由ef跟踪形成的sql,只更新修改过的字段,减少主动更新的使用,可以提高一部分性能。

 

四.参考文档

https://learn.microsoft.com/zh-cn/ef/core/modeling/value-comparers?tabs=ef5

posted @ 2023-08-08 17:01  浅草青晨  阅读(85)  评论(0编辑  收藏  举报