精华内容
下载资源
问答
  • Linq 多层嵌套查询

    千次阅读 2017-08-29 10:38:08
    var query1 = from p in dbContent.PostService where p.post_type == "product" && (from ot1 in dbContent.OrderItemmetaService where
     var query1 = from p in dbContent.PostService
                  where p.post_type == "product" &&
                      (from ot1 in dbContent.OrderItemmetaService
                       where
                           (from ot2 in dbContent.OrderItemsService
                            where ot2.order_item_type == "line_item" &&
                                (from p1 in dbContent.PostService
                                 where p1.post_type == "shop_order" && p1.post_author == userid && p1.post_status == "wc-completed"
                                 select p1.ID).Contains(ot2.order_id)
                            select ot2.order_item_id).Contains(ot1.meta_id)
                       select ot1.meta_value).Contains(p.ID)
                  select new
                  {
                      id = p.ID,
                      name = p.post_title
                  };
    
    
     var query2 = dbContent.PostService.Where(p =>
         p.post_type == "product" &&
         (dbContent.OrderItemmetaService.Where(ot1 =>
             (dbContent.OrderItemsService.Where(ot2 =>
                 ot2.order_item_type == "line_item" && (dbContent.PostService.Where(p1 =>
                     p1.post_type == "shop_order" && p1.post_author == userid && p1.post_status == "wc-completed").Select(p1 => p1.ID).Contains(ot2.order_item_id))
                     ).Select(ot2 => ot2.order_item_id).Contains(ot1.meta_id))
                     ).Select(ot1 => ot1.meta_value).Contains(p.ID))
                     ).Select(p => new
                     {
                         id = p.ID,
                         name = p.post_title
    

    }).ToList();

    Left Join 查询

    from d in Doctors
    join c in ((from t in Commentaries where t.State != 'D' group t by new { t.DoctorID } into g 
            select new {
                    DoctorID = (Int64?)g.Key.DoctorID,
                   Total = (Int32?)g.Sum(p => p.Rating),
                     Evaluate = (System.Double?)g.Average(p => p.Rating)
                               })) 
    on new { UserID = d.UserID } equals new { UserID = (Int64)c.DoctorID }
    into a_join from p in a_join.DefaultIfEmpty()
    select new {
      d.ID,
      UserID = (Int64?)d.UserID,
      d.Name,
      Evaluate = ((int?)p.Evaluate ?? (int?)0)
    }

    Lambda表达式


    Doctors .GroupJoin (Commentaries.Where (t => ((Int32)(t.State) != 68)).GroupBy ( t => new  
                   {
                      DoctorID = t.DoctorID
                   } ).Select ( g => new  
                   {
                      DoctorID = (Int64?)(g.Key.DoctorID), 
                      Total = (Int32?)(g.Sum (p => p.Rating)), 
                      Evaluate = (Double?)(g.Average (p => p.Rating))
                   } ),  d =>  new  {UserID = d.UserID},  c => new   { UserID = (Int64)(c.DoctorID)}, (d, a_join) => new   { d = d,  a_join = a_join})
                   .SelectMany (temp0 => temp0.a_join.DefaultIfEmpty (), (temp0, p) => 
             new  
             {
                ID = temp0.d.ID, 
                UserID = (Int64?)(temp0.d.UserID), 
                Name = temp0.d.Name, 
                Evaluate = ((Int32?)(p.Evaluate) ?? (Int32?)0)
             }
       )


    
    
    展开全文
  • Linq 是 C# 中一个非常好用的集合处理库,用好了能帮我们简化大量又臭又长的嵌套循环,使处理逻辑清晰可见。EF 查询主要也是依赖 Linq。但是 Linq 相对 sql 也存在一些缺点,最主要的就是动态构造查询的难度。sql 只...

    前言
    Linq 是 C# 中一个非常好用的集合处理库,用好了能帮我们简化大量又臭又长的嵌套循环,使处理逻辑清晰可见。EF 查询主要也是依赖 Linq。但是 Linq 相对 sql 也存在一些缺点,最主要的就是动态构造查询的难度。sql 只需要简单进行字符串拼接,操作难c#教程度很低(当然出错也相当容易),而 Linq 表达式由于对强类型表达式树的依赖,动态构造查询表达式基本相当于手写 AST(抽象语法树),可以说难度暴增。

       AST 已经进入编译原理的领域,对计算机系统的了解程度需求比一般 crud 写业务代码高了几个量级,也导致很多人觉得 EF 不好用,为了写个动态查询要学编译原理这个代价还是挺高的。后来也有一些类似 DynamicLinq 的类库能用表达式字符串写动态查询。
    
       本着学习精神,研究了一段时间,写了一个在我的想象力范围内,可以动态构造任意复杂的 Where 表达式的辅助类。这个辅助类的过滤条件使用了 JqGrid 的高级查询的数据结构,这是我第一个知道能生成复杂嵌套查询,并且查询数据使用 json 方便解析的 js 表格插件。可以无缝根据 JqGrid 的高级查询生成 Where 表达式。
    

    正文
    实现
    JqGrid 高级查询数据结构定义,用来反序列化:

     1     public class JqGridParameter
     2     {
     3         /// <summary>
     4         /// 是否搜索,本来应该是bool,true
     5         /// </summary>
     6         public string _search { get; set; }
     7         /// <summary>
     8         /// 请求发送次数,方便服务器处理重复请求
     9         /// </summary>
    10         public long Nd { get; set; }
    11         /// <summary>
    12         /// 当页数据条数
    13         /// </summary>
    14         public int Rows { get; set; }
    15         /// <summary>
    16         /// 页码
    17         /// </summary>
    18         public int Page { get; set; }
    19         /// <summary>
    20         /// 排序列,多列排序时为排序列名+空格+排序方式,多个列之间用逗号隔开。例:id asc,name desc
    21         /// </summary>
    22         public string Sidx { get; set; }
    23         /// <summary>
    24         /// 分离后的排序列
    25         /// </summary>
    26         public string[][] SIdx => Sidx.Split(", ").Select(s => s.Split(" ")).ToArray();
    27         /// <summary>
    28         /// 排序方式:asc、desc
    29         /// </summary>
    30         public string Sord { get; set; }
    31         /// <summary>
    32         /// 高级搜索条件json
    33         /// </summary>
    34         public string Filters { get; set; }
    35 
    36         /// <summary>
    37         /// 序列化的高级搜索对象
    38         /// </summary>
    39         public JqGridSearchRuleGroup FilterObject => Filters.IsNullOrWhiteSpace()
    40             ? new JqGridSearchRuleGroup { Rules = new[] { new JqGridSearchRule { Op = SearchOper, Data = SearchString, Field = SearchField } } }
    41             : JsonSerializer.Deserialize<JqGridSearchRuleGroup>(Filters ?? string.Empty);
    42 
    43         /// <summary>
    44         /// 简单搜索字段
    45         /// </summary>
    46         public string SearchField { get; set; }
    47         /// <summary>
    48         /// 简单搜索关键字
    49         /// </summary>
    50         public string SearchString { get; set; }
    51         /// <summary>
    52         /// 简单搜索操作
    53         /// </summary>
    54         public string SearchOper { get; set; }
    55 
    56     }
    57 
    58     /// <summary>
    59     /// 高级搜索条件组
    60     /// </summary>
    61     public class JqGridSearchRuleGroup
    62     {
    63         /// <summary>
    64         /// 条件组合方式:and、or
    65         /// </summary>
    66         public string GroupOp { get; set; }
    67         /// <summary>
    68         /// 搜索条件集合
    69         /// </summary>
    70         public JqGridSearchRule[] Rules { get; set; }
    71         /// <summary>
    72         /// 搜索条件组集合
    73         /// </summary>
    74         public JqGridSearchRuleGroup[] Groups { get; set; }
    75     }
    76 
    77     /// <summary>
    78     /// 高级搜索条件
    79     /// </summary>
    80     public class JqGridSearchRule
    81     {
    82         /// <summary>
    83         /// 搜索字段
    84         /// </summary>
    85         public string Field { get; set; }
    86         /// <summary>
    87         /// 搜索字段的大驼峰命名
    88         /// </summary>
    89         public string PascalField => Field?.Length > 0 ? Field.Substring(0, 1).ToUpper() + Field.Substring(1) : Field;
    90         /// <summary>
    91         /// 搜索操作
    92         /// </summary>
    93         public string Op { get; set; }
    94         /// <summary>
    95         /// 搜索关键字
    96         /// </summary>
    97         public string Data { get; set; }
    98     }
    
       Where 条件生成器,代码有点多,有点复杂。不过注释也很多,稍微耐心点应该不难看懂:
    
      1     /// <summary>
      2     /// JqGrid搜索表达式扩展
      3     /// </summary>
      4     public static class JqGridSearchExtensions
      5     {
      6         //前端的(不)属于条件搜索需要传递一个json数组的字符串作为参数
      7         //为了避免在搜索字符串的时候分隔符是搜索内容的一部分导致搜索关键字出错
      8         //无论定义什么分隔符都不能完全避免这种尴尬的情况,所以使用标准的json以绝后患
      9         /// <summary>
     10         /// 根据搜索条件构造where表达式,支持JqGrid高级搜索
     11         /// </summary>
     12         /// <typeparam name="T">搜索的对象类型</typeparam>
     13         /// <param name="ruleGroup">JqGrid搜索条件组</param>
     14         /// <param name="propertyMap">属性映射,把搜索规则的名称映射到属性名称,如果属性是复杂类型,使用点号可以继续访问内部属性</param>
     15         /// <returns>where表达式</returns>
     16         public static Expression<Func<T, bool>> BuildWhere<T>(JqGridSearchRuleGroup ruleGroup, IDictionary<string, string> propertyMap)
     17         {
     18             ParameterExpression parameter = Expression.Parameter(typeof(T), "searchObject");
     19 
     20             return Expression.Lambda<Func<T, bool>>(BuildGroupExpression<T>(ruleGroup, parameter, propertyMap), parameter);
     21         }
     22 
     23         /// <summary>
     24         /// 构造搜索条件组的表达式(一个组中可能包含若干子条件组)
     25         /// </summary>
     26         /// <typeparam name="T">搜索的对象类型</typeparam>
     27         /// <param name="group">条件组</param>
     28         /// <param name="parameter">参数表达式</param>
     29         /// <param name="propertyMap">属性映射</param>
     30         /// <returns>返回bool的条件组的表达式</returns>
     31         private static Expression BuildGroupExpression<T>(JqGridSearchRuleGroup group, ParameterExpression parameter, IDictionary<string, string> propertyMap)
     32         {
     33             List<Expression> expressions = new List<Expression>();
     34             foreach (var rule in group.Rules ?? new JqGridSearchRule[0])
     35             {
     36                 expressions.Add(BuildRuleExpression<T>(rule, parameter, propertyMap));
     37             }
     38 
     39             foreach (var subGroup in group.Groups ?? new JqGridSearchRuleGroup[0])
     40             {
     41                 expressions.Add(BuildGroupExpression<T>(subGroup, parameter, propertyMap));
     42             }
     43 
     44             if (expressions.Count == 0)
     45             {
     46                 throw new InvalidOperationException("构造where子句异常,生成了0个比较条件表达式。");
     47             }
     48 
     49             if (expressions.Count == 1)
     50             {
     51                 return expressions[0];
     52             }
     53 
     54             var expression = expressions[0];
     55             switch (group.GroupOp)
     56             {
     57                 case "AND":
     58                     foreach (var exp in expressions.Skip(1))
     59                     {
     60                         expression = Expression.AndAlso(expression, exp);
     61                     }
     62                     break;
     63                 case "OR":
     64                     foreach (var exp in expressions.Skip(1))
     65                     {
     66                         expression = Expression.OrElse(expression, exp);
     67                     }
     68                     break;
     69                 default:
     70                     throw new InvalidOperationException($"不支持创建{group.GroupOp}类型的逻辑运算表达式");
     71             }
     72 
     73             return expression;
     74         }
     75 
     76         private static readonly string[] SpecialRuleOps = {"in", "ni", "nu", "nn"};
     77 
     78         /// <summary>
     79         /// 构造条件表达式
     80         /// </summary>
     81         /// <typeparam name="T">搜索的对象类型</typeparam>
     82         /// <param name="rule">条件</param>
     83         /// <param name="parameter">参数</param>
     84         /// <param name="propertyMap">属性映射</param>
     85         /// <returns>返回bool的条件表达式</returns>
     86         private static Expression BuildRuleExpression<T>(JqGridSearchRule rule, ParameterExpression parameter,
     87             IDictionary<string, string> propertyMap)
     88         {
     89             Expression l;
     90 
     91             string[] names = null;
     92             //如果实体属性名称和前端名称不一致,或者属性是一个自定义类型,需要继续访问其内部属性,使用点号分隔
     93             if (propertyMap?.ContainsKey(rule.Field) == true)
     94             {
     95                 names = propertyMap[rule.Field].Split('.', StringSplitOptions.RemoveEmptyEntries);
     96                 l = Expression.Property(parameter, names[0]);
     97                 foreach (var name in names.Skip(1))
     98                 {
     99                     l = Expression.Property(l, name);
    100                 }
    101             }
    102             else
    103             {
    104                 l = Expression.Property(parameter, rule.PascalField);
    105             }
    106 
    107             Expression r = null; //值表达式
    108             Expression e; //返回bool的各种比较表达式
    109 
    110             //属于和不属于比较是多值比较,需要调用Contains方法,而不是调用比较操作符
    111             //为空和不为空的右值为常量null,不需要构造
    112             var specialRuleOps = SpecialRuleOps;
    113 
    114             var isNullable = false;
    115             var pt = typeof(T);
    116             if(names != null)
    117             {
    118                 foreach(var name in names)
    119                 {
    120                     pt = pt.GetProperty(name).PropertyType;
    121                 }
    122             }
    123             else
    124             {
    125                 pt = pt.GetProperty(rule.PascalField).PropertyType;
    126             }
    127 
    128             //如果属性类型是可空值类型,取出内部类型
    129             if (pt.IsDerivedFrom(typeof(Nullable<>)))
    130             {
    131                 isNullable = true;
    132                 pt = pt.GenericTypeArguments[0];
    133             }
    134 
    135             //根据属性类型创建要比较的常量值表达式(也就是r)
    136             if (!specialRuleOps.Contains(rule.Op))
    137             {
    138                 switch (pt)
    139                 {
    140                     case Type ct when ct == typeof(bool):
    141                         r = BuildConstantExpression(rule, bool.Parse);
    142                         break;
    143 
    144                     #region 文字
    145 
    146                     case Type ct when ct == typeof(char):
    147                         r = BuildConstantExpression(rule, str => str[0]);
    148                         break;
    149                     case Type ct when ct == typeof(string):
    150                         r = BuildConstantExpression(rule, str => str);
    151                         break;
    152 
    153                     #endregion
    154 
    155                     #region 有符号整数
    156 
    157                     case Type ct when ct == typeof(sbyte):
    158                         r = BuildConstantExpression(rule, sbyte.Parse);
    159                         break;
    160                     case Type ct when ct == typeof(short):
    161                         r = BuildConstantExpression(rule, short.Parse);
    162                         break;
    163                     case Type ct when ct == typeof(int):
    164                         r = BuildConstantExpression(rule, int.Parse);
    165                         break;
    166                     case Type ct when ct == typeof(long):
    167                         r = BuildConstantExpression(rule, long.Parse);
    168                         break;
    169 
    170                     #endregion
    171 
    172                     #region 无符号整数
    173 
    174                     case Type ct when ct == typeof(byte):
    175                         r = BuildConstantExpression(rule, byte.Parse);
    176                         break;
    177                     case Type ct when ct == typeof(ushort):
    178                         r = BuildConstantExpression(rule, ushort.Parse);
    179                         break;
    180                     case Type ct when ct == typeof(uint):
    181                         r = BuildConstantExpression(rule, uint.Parse);
    182                         break;
    183                     case Type ct when ct == typeof(ulong):
    184                         r = BuildConstantExpression(rule, ulong.Parse);
    185                         break;
    186 
    187                     #endregion
    188 
    189                     #region 小数
    190 
    191                     case Type ct when ct == typeof(float):
    192                         r = BuildConstantExpression(rule, float.Parse);
    193                         break;
    194                     case Type ct when ct == typeof(double):
    195                         r = BuildConstantExpression(rule, double.Parse);
    196                         break;
    197                     case Type ct when ct == typeof(decimal):
    198                         r = BuildConstantExpression(rule, decimal.Parse);
    199                         break;
    200 
    201                     #endregion
    202 
    203                     #region 其它常用类型
    204 
    205                     case Type ct when ct == typeof(DateTime):
    206                         r = BuildConstantExpression(rule, DateTime.Parse);
    207                         break;
    208                     case Type ct when ct == typeof(DateTimeOffset):
    209                         r = BuildConstantExpression(rule, DateTimeOffset.Parse);
    210                         break;
    211                     case Type ct when ct == typeof(Guid):
    212                         r = BuildConstantExpression(rule, Guid.Parse);
    213                         break;
    214                     case Type ct when ct.IsEnum:
    215                         r = Expression.Constant(rule.Data.ToEnumObject(ct));
    216                         break;
    217 
    218                     #endregion
    219 
    220                     default:
    221                         throw new InvalidOperationException($"不支持创建{pt.FullName}类型的数据表达式");
    222                 }
    223             }
    224 
    225             if (r != null && pt.IsValueType && isNullable)
    226             {
    227                 var gt = typeof(Nullable<>).MakeGenericType(pt);
    228                 r = Expression.Convert(r, gt);
    229             }
    230 
    231             switch (rule.Op)
    232             {
    233                 case "eq": //等于
    234                     e = Expression.Equal(l, r);
    235                     break;
    236                 case "ne": //不等于
    237                     e = Expression.NotEqual(l, r);
    238                     break;
    239                 case "lt": //小于
    240                     e = Expression.LessThan(l, r);
    241                     break;
    242                 case "le": //小于等于
    243                     e = Expression.LessThanOrEqual(l, r);
    244                     break;
    245                 case "gt": //大于
    246                     e = Expression.GreaterThan(l, r);
    247                     break;
    248                 case "ge": //大于等于
    249                     e = Expression.GreaterThanOrEqual(l, r);
    250                     break;
    251                 case "bw": //开头是(字符串)
    252                     if (pt == typeof(string))
    253                     {
    254                         e = Expression.Call(l, pt.GetMethod(nameof(string.StartsWith), new[] {typeof(string)}), r);
    255                     }
    256                     else
    257                     {
    258                         throw new InvalidOperationException($"不支持创建{pt.FullName}类型的开始于表达式");
    259                     }
    260 
    261                     break;
    262                 case "bn": //开头不是(字符串)
    263                     if (pt == typeof(string))
    264                     {
    265                         e = Expression.Not(Expression.Call(l, pt.GetMethod(nameof(string.StartsWith), new[] {typeof(string)}), r));
    266                     }
    267                     else
    268                     {
    269                         throw new InvalidOperationException($"不支持创建{pt.FullName}类型的不开始于表达式");
    270                     }
    271 
    272                     break;
    273                 case "ew": //结尾是(字符串)
    274                     if (pt == typeof(string))
    275                     {
    276                         e = Expression.Call(l, pt.GetMethod(nameof(string.EndsWith), new[] {typeof(string)}), r);
    277                     }
    278                     else
    279                     {
    280                         throw new InvalidOperationException($"不支持创建{pt.FullName}类型的结束于表达式");
    281                     }
    282 
    283                     break;
    284                 case "en": //结尾不是(字符串)
    285                     if (pt == typeof(string))
    286                     {
    287                         e = Expression.Not(Expression.Call(l, pt.GetMethod(nameof(string.EndsWith), new[] {typeof(string)}), r));
    288                     }
    289                     else
    290                     {
    291                         throw new InvalidOperationException($"不支持创建{pt.FullName}类型的不结束于表达式");
    292                     }
    293 
    294                     break;
    295                 case "cn": //包含(字符串)
    296                     if (pt == typeof(string))
    297                     {
    298                         e = Expression.Call(l, pt.GetMethod(nameof(string.Contains), new[] {typeof(string)}), r);
    299                     }
    300                     else
    301                     {
    302                         throw new InvalidOperationException($"不支持创建{pt.FullName}类型的包含表达式");
    303                     }
    304 
    305                     break;
    306                 case "nc": //不包含(字符串)
    307                     if (pt == typeof(string))
    308                     {
    309                         e = Expression.Not(Expression.Call(l, pt.GetMethod(nameof(string.Contains), new[] {typeof(string)}), r));
    310                     }
    311                     else
    312                     {
    313                         throw new InvalidOperationException($"不支持创建{pt.FullName}类型的包含表达式");
    314                     }
    315 
    316                     break;
    317                 case "in": //属于(是候选值列表之一)
    318                     e = BuildContainsExpression(rule, l, pt);
    319                     break;
    320                 case "ni": //不属于(不是候选值列表之一)
    321                     e = Expression.Not(BuildContainsExpression(rule, l, pt));
    322                     break;
    323                 case "nu": //为空
    324                     r = Expression.Constant(null);
    325                     e = Expression.Equal(l, r);
    326                     break;
    327                 case "nn": //不为空
    328                     r = Expression.Constant(null);
    329                     e = Expression.Not(Expression.Equal(l, r));
    330                     break;
    331                 case "bt": //区间
    332                     throw new NotImplementedException($"尚未实现创建{rule.Op}类型的比较表达式");
    333                 default:
    334                     throw new InvalidOperationException($"不支持创建{rule.Op}类型的比较表达式");
    335             }
    336 
    337             return e;
    338 
    339             static Expression BuildConstantExpression<TValue>(JqGridSearchRule jRule, Func<string, TValue> valueConvertor)
    340             {
    341                 var rv = valueConvertor(jRule.Data);
    342                 return Expression.Constant(rv);
    343             }
    344         }
    345 
    346         /// <summary>
    347         /// 构造Contains调用表达式
    348         /// </summary>
    349         /// <param name="rule">条件</param>
    350         /// <param name="parameter">参数</param>
    351         /// <param name="parameterType">参数类型</param>
    352         /// <returns>Contains调用表达式</returns>
    353         private static Expression BuildContainsExpression(JqGridSearchRule rule, Expression parameter, Type parameterType)
    354         {
    355             Expression e = null;
    356 
    357             var genMethod = typeof(Queryable).GetMethods()
    358                 .Single(m => m.Name == nameof(Queryable.Contains) && m.GetParameters().Length == 2);
    359 
    360             var jsonArray = JsonSerializer.Deserialize<string[]>(rule.Data);
    361 
    362             switch (parameterType)
    363             {
    364                 #region 文字
    365 
    366                 case Type ct when ct == typeof(char):
    367                     if (jsonArray.Any(o => o.Length != 1)) {throw new InvalidOperationException("字符型的候选列表中存在错误的候选项");}
    368                     e = CallContains(parameter, jsonArray, str => str[0], genMethod, ct);
    369                     break;
    370                 case Type ct when ct == typeof(string):
    371                     e = CallContains(parameter, jsonArray, str => str, genMethod, ct);
    372                     break;
    373 
    374                 #endregion
    375 
    376                 #region 有符号整数
    377 
    378                 case Type ct when ct == typeof(sbyte):
    379                     e = CallContains(parameter, jsonArray, sbyte.Parse, genMethod, ct);
    380                     break;
    381                 case Type ct when ct == typeof(short):
    382                     e = CallContains(parameter, jsonArray, short.Parse, genMethod, ct);
    383                     break;
    384                 case Type ct when ct == typeof(int):
    385                     e = CallContains(parameter, jsonArray, int.Parse, genMethod, ct);
    386                     break;
    387                 case Type ct when ct == typeof(long):
    388                     e = CallContains(parameter, jsonArray, long.Parse, genMethod, ct);
    389                     break;
    390 
    391                 #endregion
    392 
    393                 #region 无符号整数
    394 
    395                 case Type ct when ct == typeof(byte):
    396                     e = CallContains(parameter, jsonArray, byte.Parse, genMethod, ct);
    397                     break;
    398                 case Type ct when ct == typeof(ushort):
    399                     e = CallContains(parameter, jsonArray, ushort.Parse, genMethod, ct);
    400                     break;
    401                 case Type ct when ct == typeof(uint):
    402                     e = CallContains(parameter, jsonArray, uint.Parse, genMethod, ct);
    403                     break;
    404                 case Type ct when ct == typeof(ulong):
    405                     e = CallContains(parameter, jsonArray, ulong.Parse, genMethod, ct);
    406                     break;
    407 
    408                 #endregion
    409 
    410                 #region 小数
    411 
    412                 case Type ct when ct == typeof(float):
    413                     e = CallContains(parameter, jsonArray, float.Parse, genMethod, ct);
    414                     break;
    415                 case Type ct when ct == typeof(double):
    416                     e = CallContains(parameter, jsonArray, double.Parse, genMethod, ct);
    417                     break;
    418                 case Type ct when ct == typeof(decimal):
    419                     e = CallContains(parameter, jsonArray, decimal.Parse, genMethod, ct);
    420                     break;
    421 
    422                 #endregion
    423 
    424                 #region 其它常用类型
    425 
    426                 case Type ct when ct == typeof(DateTime):
    427                     e = CallContains(parameter, jsonArray, DateTime.Parse, genMethod, ct);
    428                     break;
    429                 case Type ct when ct == typeof(DateTimeOffset):
    430                     e = CallContains(parameter, jsonArray, DateTimeOffset.Parse, genMethod, ct);
    431                     break;
    432                 case Type ct when ct == typeof(Guid):
    433                     e = CallContains(parameter, jsonArray, Guid.Parse, genMethod, ct);
    434                     break;
    435                 case Type ct when ct.IsEnum:
    436                     e = CallContains(Expression.Convert(parameter, typeof(object)), jsonArray, enumString => enumString.ToEnumObject(ct), genMethod, ct);
    437                     break;
    438 
    439                     #endregion
    440             }
    441 
    442             return e;
    443 
    444             static MethodCallExpression CallContains<T>(Expression pa, string[] jArray, Func<string, T> selector, MethodInfo genericMethod, Type type)
    445             {
    446                 var data = jArray.Select(selector).ToArray().AsQueryable();
    447                 var method = genericMethod.MakeGenericMethod(type);
    448 
    449                 return Expression.Call(null, method, new[] { Expression.Constant(data), pa });
    450             }
    451         }
    452     }
    

    使用
    此处是在 Razor Page 中使用,内部使用的其他辅助类和前端页面代码就不贴了,有兴趣的可以在我的文章末尾找到 GitHub 项目链接:

     1         public async Task<IActionResult> OnGetUserListAsync([FromQuery]JqGridParameter jqGridParameter)
     2         {
     3             var usersQuery = _userManager.Users.AsNoTracking();
     4             if (jqGridParameter._search == "true")
     5             {
     6                 usersQuery = usersQuery.Where(BuildWhere<ApplicationUser>(jqGridParameter.FilterObject, null));
     7             }
     8 
     9             var users = usersQuery.Include(u => u.UserRoles).ThenInclude(ur => ur.Role).OrderBy(u => u.InsertOrder)
    10                 .Skip((jqGridParameter.Page - 1) * jqGridParameter.Rows).Take(jqGridParameter.Rows).ToList();
    11             var userCount = usersQuery.Count();
    12             var pageCount = Ceiling((double) userCount / jqGridParameter.Rows);
    13             return new JsonResult(
    14                 new
    15                 {
    16                     rows //数据集合
    17                         = users.Select(u => new
    18                         {
    19                             u.UserName,
    20                             u.Gender,
    21                             u.Email,
    22                             u.PhoneNumber,
    23                             u.EmailConfirmed,
    24                             u.PhoneNumberConfirmed,
    25                             u.CreationTime,
    26                             u.CreatorId,
    27                             u.Active,
    28                             u.LastModificationTime,
    29                             u.LastModifierId,
    30                             u.InsertOrder,
    31                             u.ConcurrencyStamp,
    32                             //以下为JqGrid中必须的字段
    33                             u.Id //记录的唯一标识,可在插件中配置为其它字段,但是必须能作为记录的唯一标识用,不能重复
    34                         }),
    35                     total = pageCount, //总页数
    36                     page = jqGridParameter.Page, //当前页码
    37                     records = userCount //总记录数
    38                 }
    39             );
    40         }
    
       启动项目后访问 /Identity/Manage/Users/Index 可以尝试使用。
    

    结语
    通过这次实践,深入了解了很多表达式树的相关知识,表达式树在编译流程中还算是高级结构了,耐点心还是能看懂,IL 才是真的晕,比原生汇编也好不到哪里去。C# 确实很有意思,入门简单,内部却深邃无比,在小白和大神手上完全是两种语言。Java 在 Java 8 时增加了 Stream 和 Lambda 表达式功能,一看就是在对标 Linq,不过那名字取的真是一言难尽,看代码写代码感觉如鲠在喉,相当不爽。由于 Stream 体系缺少表达式树,这种动态构造查询表达式的功能从一开始就不可能支持。再加上 Java 没有匿名类型,没有对象初始化器,每次用 Stream 就难受的一批,中间过程的数据结构也要专门写类,每个中间类还要独占一个文件,简直晕死。抄都抄不及格!

       C# 引入 var 关键字核心是为匿名类型服务,毕竟是编译器自动生成的类型,写代码的时候根本没有名字,不用 var 用什么?简化变量初始化代码只是顺带的。结果 Java 又抄一半,还是最不打紧的一半,简化变量初始化代码。真不知道搞 Java 的那帮人在想些什么。
    
    
    
       转载请完整保留以下内容并在显眼位置标注,未经授权删除以下内容进行转载盗用的,保留追究法律责任的权利!
    

    本文地址:https://www.cnblogs.com/coredx/p/12423929.html

    完整源代码:Github

    展开全文
  • var zz = from aa in quoteCaseModel.SingleProductList from bb in aa.CaseProductList where bb.Catagory == 14
      var zz = from aa in quoteCaseModel.SingleProductList
                                         from bb in aa.CaseProductList
                                         where bb.Catagory == 14
                                         select bb;

      var dkkkk = from aaaa in quoteCaseModel.ServiceProductList
                                            where strProductID.Contains(aaaa.Id.ToString())
                                            select aaaa;

    展开全文
  • linq to sql 的嵌套查询

    千次阅读 2018-02-11 15:50:05
    sql查询中要用到in 如果在linq to sql 中如何来实现呢,根据网上找到的方法如下:var query = from a in db.crm_comment join b in db.crm_user on a.shr equals b.account where ...

    sql查询中要用到in 如果在linq to sql 中如何来实现呢,根据网上找到的方法如下:

    var query = from a in db.crm_comment
                                join b in db.crm_user on a.shr equals b.account
                                where
                                (
                                from c in db.crm_detail
                                where c.customerid == id
                                select c.doc_id
                                ).Contains(a.doc_id)
                                select new
                                {
                                    doc_id = a.doc_id,
                                    detail = a.detail,
                                    status = a.status,
                                    shr = a.shr,
                                    shdate = a.shdate,
                                    name = b.name
                                };

    展开全文
  • LINQ多个操作嵌套实现

    2016-04-12 14:38:00
    获取集合,需要使用多个条件Where,排序OrderBy,查询Select一起。先来分步实现: source code: string[] stringArray = { "hgdgh", "qerty", "Haktjjy", "zcvz", "rtwrt" }; var contains = Enumerable....
  • linq语法

    2017-07-25 15:39:00
    LINQPad4.zip------linq...一:where 嵌套查询 var q=from p in db.ParkingSpace join uw in db.sys_user_web on p.yardNumber equals uw.yardNumber where (from u in db.sys_user.Where(c => (flag == true...
  • //Linq语句  NorthwindEntities db = new NorthwindEntities();  //多条件单表查询  var query = from q in db.Orders where q.OrderID > 10250 && q.OrderID  query = fro
  • 一个linq表达式,必须是以from子句开头。 var value=from v in values where v.indexof("it")>-1 select v 2复合from子句(多重嵌套查询:便于自己理解) var query=from a in aa from b in a.b where b....
  • LINQ 实战 6/11

    2012-03-31 17:10:04
    4.5.2 嵌套查询 111 4.5.3 分组 113 4.5.4 使用连接 114 4.5.5 分区 117 4.6 小结 121 第5章 超越基本的内存数据查询 122 5.1 常见使用场景 122 5.1.1 查询非泛型集合 123 5.1.2 按照多个条件分组...
  • LINQ 实战 11/11

    2012-03-31 17:19:10
    4.5.2 嵌套查询 111 4.5.3 分组 113 4.5.4 使用连接 114 4.5.5 分区 117 4.6 小结 121 第5章 超越基本的内存数据查询 122 5.1 常见使用场景 122 5.1.1 查询非泛型集合 123 5.1.2 按照多个条件分组...
  • LINQ 实战 10/11

    2012-03-31 17:17:32
    4.5.2 嵌套查询 111 4.5.3 分组 113 4.5.4 使用连接 114 4.5.5 分区 117 4.6 小结 121 第5章 超越基本的内存数据查询 122 5.1 常见使用场景 122 5.1.1 查询非泛型集合 123 5.1.2 按照多个条件分组...
  • LINQ 实战 9/11

    2012-03-31 17:15:45
    4.5.2 嵌套查询 111 4.5.3 分组 113 4.5.4 使用连接 114 4.5.5 分区 117 4.6 小结 121 第5章 超越基本的内存数据查询 122 5.1 常见使用场景 122 5.1.1 查询非泛型集合 123 5.1.2 按照多个条件分组...
  • LINQ 实战 8/11

    2012-03-31 17:13:51
    4.5.2 嵌套查询 111 4.5.3 分组 113 4.5.4 使用连接 114 4.5.5 分区 117 4.6 小结 121 第5章 超越基本的内存数据查询 122 5.1 常见使用场景 122 5.1.1 查询非泛型集合 123 5.1.2 按照多个条件分组...
  • LINQ 实战 7/11

    2012-03-31 17:12:04
    4.5.2 嵌套查询 111 4.5.3 分组 113 4.5.4 使用连接 114 4.5.5 分区 117 4.6 小结 121 第5章 超越基本的内存数据查询 122 5.1 常见使用场景 122 5.1.1 查询非泛型集合 123 5.1.2 按照多个条件分组...
  • LINQ 实战 5/11

    2012-03-31 17:07:56
    4.5.2 嵌套查询 111 4.5.3 分组 113 4.5.4 使用连接 114 4.5.5 分区 117 4.6 小结 121 第5章 超越基本的内存数据查询 122 5.1 常见使用场景 122 5.1.1 查询非泛型集合 123 5.1.2 按照多个条件分组...
  • LINQ 实战 4/11

    2012-03-31 17:05:58
    4.5.2 嵌套查询 111 4.5.3 分组 113 4.5.4 使用连接 114 4.5.5 分区 117 4.6 小结 121 第5章 超越基本的内存数据查询 122 5.1 常见使用场景 122 5.1.1 查询非泛型集合 123 5.1.2 按照多个条件分组...
  • LINQ 实战 3/11

    2012-03-31 17:03:51
    4.5.2 嵌套查询 111 4.5.3 分组 113 4.5.4 使用连接 114 4.5.5 分区 117 4.6 小结 121 第5章 超越基本的内存数据查询 122 5.1 常见使用场景 122 5.1.1 查询非泛型集合 123 5.1.2 按照多个条件分组...
  • LINQ 实战 2/11

    2012-03-31 17:01:57
    4.5.2 嵌套查询 111 4.5.3 分组 113 4.5.4 使用连接 114 4.5.5 分区 117 4.6 小结 121 第5章 超越基本的内存数据查询 122 5.1 常见使用场景 122 5.1.1 查询非泛型集合 123 5.1.2 按照多个条件分组...
  • LINQ 实战 1/11

    2012-03-31 16:59:57
    4.5.2 嵌套查询 111 4.5.3 分组 113 4.5.4 使用连接 114 4.5.5 分区 117 4.6 小结 121 第5章 超越基本的内存数据查询 122 5.1 常见使用场景 122 5.1.1 查询非泛型集合 123 5.1.2 按照多个条件分组...
  • 关于LINQ 和lambda表达式

    千次阅读 2016-05-12 11:13:32
    LINQ : LINQ表达式的from行可以嵌套 实现表多层关联一层层向下找的目的 (注意一对一还是一对多的对应关系 容易乱 别把上层过滤掉的内容又关联回来了) from r in userInfo.RoleInfo from a in r.ActionInfo ...
  • SQL中in和not in在LINQ中的写法

    千次阅读 2019-03-21 13:53:41
    1.主要是借住contains和where完成嵌套 //SQL中的in和not in语法对应的LINQ写法 //相当于查询语句:select * from listAll p where p.name not in(select f.name from listFind) var a = (from p in listAll ...
  • LINQ to SQL语句(1)之Where 2 Where操作 2 1.简单形式: 2 2.关系条件形式: 2 3.First()形式: 3 LINQ to SQL语句(2)之Select/Distinct 3 1.简单用法: 4 2.匿名类型 形式: 4 3.条件形式: 5 4.指定类 型形式: 6 ...
  • var = from in where orderby LINQ 基本子句 from查询子句——基础 后面跟随着项目名称和数据源 示例代码如下: var str = from lq in str select lq; 其中select语句指定了返回到集合变量中的元素是...
  • //ef 嵌套查询 var taskFragmentsNew = db.TaskFragments.Where(x => taskNew.Select(y => y.Id).Contains(x.TaskId)); var waveNew = db.Waves.Where(x => taskFragmentsNew.Select(y => y.Id)....
  • LinqToHubble

    2014-04-23 17:13:32
    Linqtohubble 是一个简单实用的hubbledotnet的LINQ Provider,支持Match、Contains匹配,支持Take、Skip分页,支持OrderBY排序,支持多Where嵌套,简单优化表达式放大了长词得分,数据也是延迟取的……使用步骤稍后给...

空空如也

空空如也

1 2 3
收藏数 49
精华内容 19
关键字:

linqwhere嵌套