efcore根据多个条件更新_通过Expression表达式树,为EF Core找回AddOrUpdate方法

5d0ceacd6af79ba3f84e2e249e795d5e.png

在做.NET Core开发工作的开发者们应该都知道,在EF Core之后,微软大大再也没有提供AddOrUpdate方法,但实际开发当中经常会有AddOrUpdate这样的需求,虽然能够自己根据业务进行定制化的实现,但有个通用的AddOrUpdate方法就会很实用了,而且,博主在曾经.NET Framework时代,也非常喜欢EF6的AddOrUpdate方法,经过了这么多年的不习惯,也在网络上寻找过各路方法,也不太行,虽然也有实现的,但不完美,那么今天,就再前人的坑的基础之上,给EF Core找回AddOrUpdate方法吧!

基本思路

为DbSet<T>类型添加一个扩展方法,然后我需要根据哪个属性进行数据的存在性判断,比如Id,或是手机号、身份证号等唯一键进行查存,由于查存的字段的不确定性,所以需要动态构建where的Expression,然后便可以判断传入的实体是需要新增还是更新操作。

逻辑实现

首先创建一个AddOrUpdate方法,为DbSet扩展:

public static void AddOrUpdate<T, TKey>(this DbSet<T> dbSet, Expression<Func<T, TKey>> keySelector, T entity)

其中参数keySelector是一个表达式树类型,决定传入的实体T entity根据哪个字段进行存在性判断。

如何根据keySelector表达式树来知道字段的名字是什么呢?通过表达式树编译,然后反射就知道了,通过调用keySelector的Compile方法,编译成一个Func类型的匿名函数,将entity传入func匿名函数进行调用,便可以得到entity的判重字段TKey的值,比如keySelector是一个根据字符串类型的Name查重的表达式,那么keySelector编译之后传入entity调用拿到的结果就是Name的值,代码如下:

Expression<Func<T, string>> keySelector=e=>e.Name;
var keyObject = keySelector.Compile()(entity); // 此时keyObject是一个string类型的值,该值就是entity的Name的值

但是在构造where表达式树之前,我们还需要做一件事情,就是封装Expression表达式树的参数访问,以便后续重用,在构造where表达式树,会用到表达式树的两种操作,分别是成员访问和创建新对象这两种操作,来生成我们需要的条件表达式树主体部分。比如讲上面的e=>e.Name表达式转换成e=>e.Name=="白火石"这样的形式。代码如下:

        private static Expression ReplaceParameter(Expression oldExpression, ParameterExpression newParameter)
        {
    
            return oldExpression.NodeType switch
            {
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据中缀表达式转换为表达式的算法,可以分为以下步骤: 1. 创建一个空栈和一个空的表达式。 2. 从左到右扫描中缀表达式中的每个元素。 3. 如果当前元素是操作数,则创建一个只包含该操作数的表达式,并将其压入栈中。 4. 如果当前元素是操作符,则创建一个只包含该操作符的表达式,并将其弹出栈两次,作为该操作符的左右子,然后将该表达式压入栈中。 5. 重复步骤2-4,直到扫描完整个中缀表达式。 6. 最后,栈中只剩下一个表达式,即为所求的表达式。 下面是一个Python实现的例子: ```python class TreeNode: def __init__(self, val): self.val = val self.left = None self.right = None def infix_to_expression_tree(infix): precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3} stack = [] for char in infix: if char.isalnum(): node = TreeNode(char) stack.append(node) elif char in precedence: node = TreeNode(char) while stack and stack[-1].val != '(' and precedence[char] <= precedence[stack[-1].val]: node.right = stack.pop() node.left = stack.pop() stack.append(node) stack.append(node) elif char == '(': stack.append(TreeNode(char)) elif char == ')': while stack and stack[-1].val != '(': node = stack.pop() if node.val in precedence: node.right = stack.pop() node.left = stack.pop() stack.append(node) stack.pop() while stack: node = stack.pop() if node.val in precedence: node.right = stack.pop() node.left = stack.pop() stack.append(node) return stack[0] ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值