翼度科技»论坛 编程开发 .net 查看内容

EFCore 动态拼接查询条件(表达式树方式)

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
扩展方法名:Filter
支持参数:实体类、JObject
扩展代码:
  1. //白色风车
  2. public static class EntityFrameworkCoreExtensions
  3.     {
  4.         private static DbCommand CreateCommand(DatabaseFacade facade, string sql, out DbConnection connection, params object[] parameters)
  5.         {
  6.             var conn = facade.GetDbConnection();
  7.             connection = conn;
  8.             if (conn.State != ConnectionState.Open)
  9.             {
  10.                 conn.Open();
  11.             }
  12.             var cmd = conn.CreateCommand();
  13.             cmd.CommandText = sql;
  14.             cmd.Parameters.AddRange(parameters);
  15.             return cmd;
  16.         }
  17.         public static DataTable SqlQuery(this DatabaseFacade facade, string sql, params object[] parameters)
  18.         {
  19.             var command = CreateCommand(facade, sql, out DbConnection conn, parameters);
  20.             var reader = command.ExecuteReader();
  21.             var dt = new DataTable();
  22.             dt.Load(reader);
  23.             reader.Close();
  24.             conn.Close();
  25.             return dt;
  26.         }
  27.         public static List<T> SqlQuery<T>(this DatabaseFacade facade, string sql, params object[] parameters) where T : class, new()
  28.         {
  29.             var dt = SqlQuery(facade, sql, parameters);
  30.             return dt.ToList<T>();
  31.         }
  32.         public static List<T> ToList<T>(this DataTable dt) where T : class, new()
  33.         {
  34.             var propertyInfos = typeof(T).GetProperties();
  35.             var list = new List<T>();
  36.             foreach (DataRow row in dt.Rows)
  37.             {
  38.                 var t = new T();
  39.                 foreach (PropertyInfo p in propertyInfos)
  40.                 {
  41.                     if (dt.Columns.IndexOf(p.Name) != -1 && row[p.Name] != DBNull.Value)
  42.                         p.SetValue(t, row[p.Name], null);
  43.                 }
  44.                 list.Add(t);
  45.             }
  46.             return list;
  47.         }
  48.         //public static List<T> DTToList<T>(this DataTable dt)
  49.         //{
  50.         //    var dataColumn = dt.Columns.Cast<DataColumn>().Select(c => c.ColumnName).ToList();
  51.         //    var properties = typeof(T).GetProperties();
  52.         //    string columnName = string.Empty;
  53.         //    return dt.AsEnumerable().Select(row =>
  54.         //    {
  55.         //        var t = Activator.CreateInstance<T>();
  56.         //        foreach (var p in properties)
  57.         //        {
  58.         //            columnName = p.Name;
  59.         //            if (dataColumn.Contains(columnName))
  60.         //            {
  61.         //                if (!p.CanWrite)
  62.         //                    continue;
  63.         //                object value = row[columnName];
  64.         //                Type type = p.PropertyType;
  65.         //                if (value != DBNull.Value)
  66.         //                {
  67.         //                    p.SetValue(t, Convert.ChangeType(value, type), null);
  68.         //                }
  69.         //            }
  70.         //        }
  71.         //        return t;
  72.         //    }).ToList();
  73.         //}
  74.         public static DataTable ToDataTable<T>(this List<T> items)
  75.         {
  76.             DataTable dataTable = new DataTable();
  77.             PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
  78.             foreach (PropertyInfo prop in Props)
  79.             {
  80.                 dataTable.Columns.Add(prop.Name, prop.PropertyType);
  81.             }
  82.             foreach (T obj in items)
  83.             {
  84.                 var values = new object[Props.Length];
  85.                 for (int i = 0; i < Props.Length; i++)
  86.                 {
  87.                     values[i] = Props[i].GetValue(obj, null);
  88.                 }
  89.                 dataTable.Rows.Add(values);
  90.             }
  91.             return dataTable;
  92.         }
  93.         /// <summary>
  94.         /// WhereIf扩展
  95.         /// </summary>
  96.         /// <typeparam name="T"></typeparam>
  97.         /// <param name="query"></param>
  98.         /// <param name="condition"></param>
  99.         /// <param name="predicate"></param>
  100.         /// <returns></returns>
  101.         public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, bool>> predicate)
  102.         {
  103.             return condition ? query.Where(predicate) : query;
  104.         }
  105.         /// <summary>
  106.         /// WhereIf扩展
  107.         /// </summary>
  108.         /// <typeparam name="T"></typeparam>
  109.         /// <param name="query"></param>
  110.         /// <param name="condition"></param>
  111.         /// <param name="predicate"></param>
  112.         /// <returns></returns>
  113.         public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, int, bool>> predicate)
  114.         {
  115.             return condition ? query.Where(predicate) : query;
  116.         }
  117.         /// <summary>
  118.         /// WhereIf扩展
  119.         /// </summary>
  120.         /// <typeparam name="T"></typeparam>
  121.         /// <param name="query"></param>
  122.         /// <param name="condition"></param>
  123.         /// <param name="predicate"></param>
  124.         /// <returns></returns>
  125.         public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> query, bool condition, Func<T, bool> predicate)
  126.         {
  127.             return condition ? query.Where(predicate) : query;
  128.         }
  129.         /// <summary>
  130.         /// 条件筛选过滤  (字段的名称、类型一致)
  131.         /// </summary>
  132.         /// <typeparam name="T">源数据</typeparam>
  133.         /// <typeparam name="R">筛选参数实体</typeparam>
  134.         /// <param name="query">属性标识[JsonIgnore] 设置该属性不作筛选字段</param>
  135.         /// <param name="condition">属性标识[JsonIgnore] 设置该属性不作筛选字段</param>
  136.         /// <returns></returns>
  137.         public static IQueryable<T> Filter<T, R>(this IQueryable<T> query, R condition) where R : new()
  138.         {
  139.             //参考 https://www.cnblogs.com/ma-nong01/p/14323430.html https://www.cnblogs.com/doudouzi/p/11897731.html
  140.             var dbsel = typeof(T).GetProperties().Where(p => p.CanWrite && !p.CustomAttributes.Any(x => x.AttributeType == typeof(JsonIgnoreAttribute) || x.AttributeType == typeof(NotMappedAttribute))).ToList();
  141.             var con = condition.GetType().GetProperties().Where(p => p.CanWrite && !p.CustomAttributes.Any(x => x.AttributeType == typeof(JsonIgnoreAttribute) || x.AttributeType == typeof(NotMappedAttribute))).ToList();
  142.             List<MethodCallExpression> mcList = new List<MethodCallExpression>();
  143.             List<BinaryExpression> mcList2 = new List<BinaryExpression>();
  144.             ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "x");
  145.             List<Expression> listexp = new List<Expression>();
  146.             foreach (var item in dbsel)
  147.             {
  148.                 foreach (var p in con)
  149.                 {
  150.                     var name = p.Name;
  151.                     if (name.ToLower() == item.Name.ToLower())
  152.                     {
  153.                         var type = p.PropertyType;
  154.                         var val = p.GetValue(condition, null);
  155.                         if (val != null)
  156.                         {
  157.                             //字符串不为空
  158.                             if (!(type.Name == "String" && string.IsNullOrEmpty(val.ToString())))
  159.                             {
  160.                                 //传入的是数组
  161.                                 if (type.Name == "List`1")
  162.                                 {
  163.                                     //泛型里的类型与筛选值的类型一致
  164.                                     if (type.GetGenericArguments()?.FirstOrDefault() == item.PropertyType && ((ICollection)val).Count > 0)
  165.                                     {
  166.                                         //参考 https://www.likecs.com/ask-4358604.html#sc=2800
  167.                                         var methodInfo = type.GetMethod("Contains", new Type[] { item.PropertyType });
  168.                                         var list = Expression.Constant(val);
  169.                                         //var param = Expression.Parameter(typeof(T), "j");
  170.                                         var value = Expression.Property(parameterExpression, item);
  171.                                         var body = Expression.Call(list, methodInfo, value);
  172.                                         listexp.Add(body);
  173.                                     }
  174.                                 }
  175.                                 //类型一致
  176.                                 else if (item.PropertyType == type)
  177.                                 {
  178.                                     MemberExpression proerty = Expression.Property(parameterExpression, item);
  179.                                     ConstantExpression constantExpression = Expression.Constant(val, item.PropertyType);
  180.                                     if (item.PropertyType.Name == "String")
  181.                                     {
  182.                                         listexp.Add(Expression.Call(proerty, typeof(string).GetMethod("Contains", new Type[] { item.PropertyType }), new Expression[] { constantExpression }));
  183.                                     }
  184.                                     //else if (item.PropertyType.Name == "Boolean")
  185.                                     //{
  186.                                     //    listexp.Add(Expression.Call(proerty, typeof(bool).GetMethod("Equals", new Type[] { typeof(bool) }), new Expression[] { constantExpression }));
  187.                                     //}
  188.                                     //else if (item.PropertyType.Name == "Int32" /*&& !val.ToString().Equals("0")*/)
  189.                                     //{
  190.                                     //    listexp.Add(Expression.Call(proerty, typeof(int).GetMethod("Equals", new Type[] { typeof(int) }), new Expression[] { constantExpression }));
  191.                                     //}
  192.                                     else if (item.PropertyType.Name == "DateTime")
  193.                                     {
  194.                                         if (DateTime.TryParse(val?.ToString(), out DateTime parsedDate))
  195.                                         {
  196.                                             var constant = Expression.Constant(parsedDate.Date);
  197.                                             var property = Expression.Property(proerty, "Date");
  198.                                             var exp1 = Expression.Equal(property, constant);
  199.                                             listexp.Add(exp1);
  200.                                         }
  201.                                     }
  202.                                     //else if (item.PropertyType.Name == "Decimal")
  203.                                     //{
  204.                                     //    listexp.Add(Expression.Call(proerty, typeof(decimal).GetMethod("Equals", new Type[] { typeof(decimal) }), new Expression[] { constantExpression }));
  205.                                     //}
  206.                                     //else if (item.PropertyType.Name != "Int32" && item.PropertyType.Name != "ICollection`1" && item.PropertyType.Name != "Nullable`1")
  207.                                     //{
  208.                                     //    listexp.Add(Expression.Call(proerty, typeof(string).GetMethod("Contains", new Type[] { item.PropertyType }), new Expression[] { constantExpression }));
  209.                                     //}
  210.                                     else if (item.PropertyType.Name == "ICollection`1")
  211.                                     {
  212.                                     }
  213.                                     else if (item.PropertyType.Name == "Nullable`1"/* && !val.ToString().Equals("0")*/)
  214.                                     {
  215.                                         if (type.GetGenericArguments()?.FirstOrDefault() == typeof(DateTime))
  216.                                         {
  217.                                             if (DateTime.TryParse(val?.ToString(), out DateTime parsedDate))
  218.                                             {
  219.                                                 var constant = Expression.Constant(parsedDate.Date);
  220.                                                 var property = Expression.Property(proerty, "Value");
  221.                                                 property = Expression.Property(property, "Date");
  222.                                                 var exp1 = Expression.Equal(property, constant);
  223.                                                 listexp.Add(exp1);
  224.                                             }
  225.                                         }
  226.                                         else
  227.                                         {
  228.                                             listexp.Add(Expression.Equal(proerty, constantExpression));
  229.                                         }
  230.                                     }
  231.                                     else
  232.                                     {
  233.                                         listexp.Add(Expression.Equal(proerty, constantExpression));
  234.                                     }
  235.                                 }
  236.                                 break;
  237.                             }
  238.                         }
  239.                     }
  240.                 }
  241.             }
  242.             Expression<Func<T, bool>> exp = Expression.Lambda<Func<T, bool>>(MethodCall(listexp), new ParameterExpression[] { parameterExpression });
  243.             return exp != null ? query.Where(exp) : query;
  244.         }
  245.         /// <summary>
  246.         /// 条件筛选过滤
  247.         /// </summary>
  248.         /// <typeparam name="T">源数据</typeparam>
  249.         /// <param name="query">属性标识[JsonIgnore] 设置该属性不作筛选字段</param>
  250.         /// <param name="Jobj">JObject 筛选参数</param>
  251.         /// <returns></returns>
  252.         public static IQueryable<T> Filter<T>(this IQueryable<T> query, JObject Jobj) where T : new()
  253.         {
  254.             var condition = Jobj.ToObject<T>();
  255.             return query.Filter(condition);
  256.         }
  257.         /// <summary>
  258.         /// 递归拼接 条件
  259.         /// </summary>
  260.         /// <param name="conditions"></param>
  261.         /// <returns></returns>
  262.         private static Expression MethodCall(IEnumerable<Expression> conditions)
  263.         {
  264.             if (conditions == null || conditions.Count() == 0)
  265.             {
  266.                 return Expression.Constant(true, typeof(bool));
  267.             }
  268.             else if (conditions.Count() == 1)
  269.             {
  270.                 return conditions.First();
  271.             }
  272.             else
  273.             {
  274.                 Expression left = MethodCall(conditions.Take(1).ToList());
  275.                 Expression right = MethodCall(conditions.Skip(1).ToList());
  276.                 return Expression.AndAlso(left, right);
  277.             }
  278.         }
  279.     }
复制代码
View Code用法:
var list=db.tableA.Filter(obj).ToList();
 
出处:[url=https://www.cnblogs.com/zszh/p/17012510.html]https://www.cnblogs.com/zszh/p/17012510.html[/url]
来源:https://www.cnblogs.com/zszh/archive/2022/12/29/17012510.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
来自手机

举报 回复 使用道具