C# Expression使用实践——为FreeSql增加WhereLike方法
2022/7/7 2:20:17
本文主要是介绍C# Expression使用实践——为FreeSql增加WhereLike方法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1.背景
前端有一个是否模糊查询的参数,当未勾选时,所有字符串类型的值使用a = 'xxx'
,勾选后使用a like '%xxx%'
如果使用WhereIf来写,每一个判断条件都需要写两行
.WhereIf(!request.IsLike && request.A.HasValue(), (i, o) => o.A== request.A) .WhereIf(request.IsLike && request.A.HasValue(), (i, o) => o.A.Contains(request.A))
2.初次尝试
public static ISelect<T1, T2> WhereLike<T1, T2>(this ISelect<T1, T2> query, Func<HzyTuple<T1, T2>, string> filed, string value, bool isLike = false) where T2 : class { if (isLike) { query = query.Where(x => filed(x).Contains(value)); } else { query = query.Where(x => filed(x) == value); } return query; } public static ISelect<T1, T2> WhereLike<T1, T2>(this ISelect<T1, T2> query, Func<T1, T2, string> filed, string value, bool isLike = false) where T2 : class { if (isLike) { query = query.Where(x => filed(x.t1, x.t2).Contains(value)); } else { query = query.Where(x => filed(x.t1, x.t2) == value); } return query; }
执行后,发现生成的sql语句不正确where = 'xxx'
,少了字段名,猜测FreeSql底层表达式解析可能不支持这种写法
3.解决办法
开始大量Google Expression 相关资料,最终找到了解决办法
public static ISelect<T1> WhereLike<T1>(this ISelect<T1> query, Expression<Func<T1, string>> filed, string value, bool isLike = false) where T1 : class { var valueExp = Expression.Constant(value); if (isLike) { var method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); query = query.Where(Expression.Lambda<Func<T1, bool>>(Expression.Call(filed.Body, method, valueExp), filed.Parameters)); } else { query = query.Where(Expression.Lambda<Func<T1, bool>>(Expression.Equal(filed.Body, valueExp), filed.Parameters)); } return query; } #region HzyTuple public static ISelect<T1, T2> WhereLike<T1, T2>(this ISelect<T1, T2> query, Expression<Func<HzyTuple<T1, T2>, string>> filed, string value, bool isLike = false) where T2 : class { var valueExp = Expression.Constant(value); if (isLike) { var method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); query = query.Where(Expression.Lambda<Func<HzyTuple<T1, T2>, bool>>(Expression.Call(filed.Body, method, valueExp), filed.Parameters)); } else { query = query.Where(Expression.Lambda<Func<HzyTuple<T1, T2>, bool>>(Expression.Equal(filed.Body, valueExp), filed.Parameters)); } return query; } #endregion #region Not HzyTuple public static ISelect<T1, T2> WhereLike<T1, T2>(this ISelect<T1, T2> query, Expression<Func<T1, T2, string>> filed, string value, bool isLike = false) where T2 : class { var valueExp = Expression.Constant(value); if (isLike) { var method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); query = query.Where(Expression.Lambda<Func<T1, T2, bool>>(Expression.Call(filed.Body, method, valueExp), filed.Parameters)); } else { query = query.Where(Expression.Lambda<Func<T1, T2, bool>>(Expression.Equal(filed.Body, valueExp), filed.Parameters)); } return query; } #endregion
4.附
以上表达式代码有一定规律,一个个写太费时间了,所以搞了个python脚本生成代码
脚本如下
max = 16 def PrintHzyTuple(number): TValue = ', '.join(['T'+str(i+1) for i in range(number)]) TWhere = '' for i in range(number-1): TWhere += f' where T{str(i+2)} : class\n' template = f''' public static ISelect<{TValue}> WhereLike<{TValue}>(this ISelect<{TValue}> query, Expression<Func<HzyTuple<{TValue}>, string>> filed, string value, bool isLike = false) {TWhere} {{ var valueExp = Expression.Constant(value); if (isLike) {{ var method = typeof(string).GetMethod("Contains", new[] {{ typeof(string) }}); query = query.Where(Expression.Lambda<Func<HzyTuple<{TValue}>, bool>>(Expression.Call(filed.Body, method, valueExp), filed.Parameters)); }} else {{ query = query.Where(Expression.Lambda<Func<HzyTuple<{TValue}>, bool>>(Expression.Equal(filed.Body, valueExp), filed.Parameters)); }} return query; }} ''' print(template) def PrintNotHzyTuple(number): TValue = ', '.join(['T'+str(i+1) for i in range(number)]) TWhere = '' for i in range(number-1): TWhere += f' where T{str(i+2)} : class\n' template = f''' public static ISelect<{TValue}> WhereLike<{TValue}>(this ISelect<{TValue}> query, Expression<Func<{TValue}, string>> filed, string value, bool isLike = false) {TWhere} {{ var valueExp = Expression.Constant(value); if (isLike) {{ var method = typeof(string).GetMethod("Contains", new[] {{ typeof(string) }}); query = query.Where(Expression.Lambda<Func<{TValue}, bool>>(Expression.Call(filed.Body, method, valueExp), filed.Parameters)); }} else {{ query = query.Where(Expression.Lambda<Func<{TValue}, bool>>(Expression.Equal(filed.Body, valueExp), filed.Parameters)); }} return query; }} ''' print(template) def RunHzyTuple(num,start = 2): if start < num: PrintHzyTuple(start) start += 1 RunHzyTuple(num,start) else: PrintHzyTuple(start) def RunNotHzyTuple(num,start = 2): if start < num: PrintNotHzyTuple(start) start += 1 RunNotHzyTuple(num,start) else: PrintNotHzyTuple(start) if __name__=="__main__": print(''' public static ISelect<T1> WhereLike<T1>(this ISelect<T1> query, Expression<Func<T1, string>> filed, string value, bool isLike = false) where T1 : class { var valueExp = Expression.Constant(value); if (isLike) { var method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); query = query.Where(Expression.Lambda<Func<T1, bool>>(Expression.Call(filed.Body, method, valueExp), filed.Parameters)); } else { query = query.Where(Expression.Lambda<Func<T1, bool>>(Expression.Equal(filed.Body, valueExp), filed.Parameters)); } return query; } ''') print(" #region HzyTuple") RunHzyTuple(16) print(" #endregion\n\n") print(" #region Not HzyTuple") RunNotHzyTuple(16) print(" #endregion")
这篇关于C# Expression使用实践——为FreeSql增加WhereLike方法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-03-01沐雪多租宝商城源码从.NetCore3.1升级到.Net6的步骤
- 2024-12-06使用Microsoft.Extensions.AI在.NET中生成嵌入向量
- 2024-11-18微软研究:RAG系统的四个层次提升理解与回答能力
- 2024-11-15C#中怎么从PEM格式的证书中提取公钥?-icode9专业技术文章分享
- 2024-11-14云架构设计——如何用diagrams.net绘制专业的AWS架构图?
- 2024-05-08首个适配Visual Studio平台的国产智能编程助手CodeGeeX正式上线!C#程序员必备效率神器!
- 2024-03-30C#设计模式之十六迭代器模式(Iterator Pattern)【行为型】
- 2024-03-29c# datetime tryparse
- 2024-02-21list find index c#
- 2024-01-24convert toint32 c#