亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

.NET深入實戰系列--EF到底怎么寫過濾條件

2019-11-14 14:04:43
字體:
來源:轉載
供稿:網友

    本文唯一訪問地址:http://www.49028c.com/yubaolee/p/DynamicLinq.html

    對于系統開發來說,按不同字段進行過濾查詢是一種常見的需求。在EF中通常的做法是:

        /// <summary>        /// 只是簡單舉例,只用了兩個過濾條件        /// </summary>        IEnumerable<UserInfo> Search(string username = "", string usertype = "")        {            var query = _context.UserInfoes.AsQueryable();            if (!string.IsNullOrEmpty(username))                query = query.Where(u => u.UserName == username);            if (!string.IsNullOrEmpty(usertype))                query = query.Where(u => u.UserType == usertype);            return query.ToList();        }

    這時如果我有一個新的需求,比如查詢用戶名中必須包含不定個數關鍵字的用戶。那我們可以用參數數組做類似下面的升級

  PRivate IEnumerable<UserInfo> Search(params string[] keys)        {            var query = _context.UserInfoes.AsQueryable();            foreach (var key in keys)            {                query = query.Where(u => u.UserName.Contains(key));            }            return query.ToList();        }

    上面的代碼都是能夠良好運行的,這時如果需求變成了:查詢用戶名中至少包含一個關鍵字的用戶,那我們該如何處理?很明顯要用到Or運算,但怎么處理才是最合理的?普通的查詢已經不能很好的解決該問題。于是Joe Albahari大神在他的一篇博文中使用PredicateBuilder輕松地解決了該問題:

   IQueryable<UserInfo> Search(params string[] keys)        {            var predicate = PredicateBuilder.False<UserInfo>();            foreach (string keyWord in keys)            {                predicate = predicate.Or(p => p.UserName.Contains(keyword));            }            return _context.UserInfoes.Where(predicate);        }

    至于PredicateBuilder的實現可以去他的博文中查看或者直接在nuget中查找添加LINQKit引用。PredicateBuilder很好的解決的動態生成Lambda問題,支持And/Or等主流運算。但它仍沒能解決一個問題:如果查詢條件中的屬性(即數據庫中的字段)也是不確定的,這樣該如何處理?

    這時Scott大神站出來了。在他的博客Dynamic LINQ (Part 1: Using the LINQ Dynamic Query Library)中,他把EF整成了拼接SQL的方式來實現這個需求。如下:

  private IQueryable<UserInfo> Search(string key, string value)        {            return _context.UserInfoes.Where("@0 ='@1'", key, value);        }

    這樣我們就不怕無盡變更的需求,想怎么調用都可以:

 var users = Search("UserNmae", "yubaolee");  //過濾用戶名var users2 = Search("UserType", "administrator"); //過濾用戶類型

    你也可以使用Key-Value之類的組合成更強大的查詢函數。然,世界上的事情總不是那么美好的。你會在實踐中用著用著發現,丫竟然不支持 like,用著用著發現,丫竟然不支持guid等等。

    唉!我去,我等向來拿來就用之流,竟然會碰到這種鳥事。還是自己動手吧!

    好吧,下面才是博文主要內容,如果少年你沒看到下面,嘖嘖!著實有些可惜&hellip;

 

    分析一下我們的需求:

  1. 可以根據用戶提交過來的字符串還得到他想查找的屬性(或數據庫字段);
  2. 可以把傳過來的操作轉成一個比較型的lambda表達式;
  3. 得把該表達式傳到EF查詢的Where中;

    根據上面的需求,我們可以借鑒一下PredicateBuilder的實現方式,用表達式樹來生成動態lambda,然后傳到ef的過濾條件中。如下:

 public class Filter    {        public string Key { get; set; } //過濾的關鍵字        public string Value { get; set; } //過濾的值        public string Contract { get; set; }// 過濾的約束 比如:'<' '<=' '>' '>=' 'like'等    }    public static class DynamicLinq    {        /// <summary>        /// 創建lambda中的參數,即c=>c.xxx==xx 中的c        /// </summary>        public static ParameterExpression CreateLambdaParam<T>(string name)        {            return Expression.Parameter(typeof(T), name);        }        /// <summary>        /// 創建linq表達示的body部分,即c=>c.xxx==xx 中的c.xxx==xx        /// </summary>        public static Expression GenerateBody<T>(this ParameterExpression param, Filter filterObj)        {            PropertyInfo property = typeof(T).GetProperty(filterObj.Key);            //組裝左邊            Expression left = Expression.Property(param, property);            //組裝右邊            Expression right = null;            //todo: 下面根據需要,擴展自己的類型            if (property.PropertyType == typeof(int))            {                right = Expression.Constant(int.Parse(filterObj.Value));            }            else if (property.PropertyType == typeof(DateTime))            {                right = Expression.Constant(DateTime.Parse(filterObj.Value));            }            else if (property.PropertyType == typeof(string))            {                right = Expression.Constant((filterObj.Value));            }            else if (property.PropertyType == typeof(decimal))            {                right = Expression.Constant(decimal.Parse(filterObj.Value));            }            else if (property.PropertyType == typeof(Guid))            {                right = Expression.Constant(Guid.Parse(filterObj.Value));            }            else if (property.PropertyType == typeof(bool))            {                right = Expression.Constant(filterObj.Value.Equals("1"));            }            else            {                throw new Exception("暫不能解析該Key的類型");            }            //todo: 下面根據需要擴展自己的比較            Expression filter = Expression.Equal(left, right);            switch (filterObj.Contract)            {                case "<=":                    filter = Expression.LessThanOrEqual(left, right);                    break;                case "<":                    filter = Expression.LessThan(left, right);                    break;                case ">":                    filter = Expression.GreaterThan(left, right);                    break;                case ">=":                    filter = Expression.GreaterThanOrEqual(left, right);                    break;                case "like":                    filter = Expression.Call(left, typeof(string).GetMethod("Contains", new[] { typeof(string) }),                                 Expression.Constant(filterObj.Value));                    break;            }            return filter;        }        /// <summary>        /// 創建完整的lambda,即c=>c.xxx==xx        /// </summary>        public static LambdaExpression GenerateLambda(this ParameterExpression param, Expression body)        {            return Expression.Lambda(body, param);        }        /// <summary>        /// 創建完整的lambda,為了兼容EF中的where語句        /// </summary>        public static Expression<Func<T, bool>> GenerateTypeLambda<T>(this ParameterExpression param, Expression body)        {            return (Expression<Func<T, bool>>)(param.GenerateLambda(body));        }        public static Expression AndAlso(this Expression expression, Expression expressionRight)        {            return Expression.AndAlso(expression, expressionRight);        }        public static Expression Or(this Expression expression, Expression expressionRight)        {            return Expression.Or(expression, expressionRight);        }        public static Expression And(this Expression expression, Expression expressionRight)        {            return Expression.And(expression, expressionRight);        }    }

    來看看我們客戶端的調用:

//模擬過濾對象            var filters = new Filter[]            {                new Filter {Key = "UserName", Value = "yubaolee", Contract = "like"},                new Filter {Key = "UserType", Value = "administrator", Contract = "="}            };            var param = DynamicLinq.CreateLambdaParam<UserInfo>("c");            Expression body = Expression.Constant(true); //初始默認一個true            foreach (var filter in filters)            {                body = body.AndAlso(param.GenerateBody<UserInfo>(filter)); //這里可以根據需要自由組合            }            var lambda = param.GenerateTypeLambda<UserInfo>(body);  //最終組成lambda                      var users = _context.UserInfoes.Where(lambda);  //得到最終結果            Console.Read();

    這時我們可以自由組合,但客戶端代碼量看起來好像不少。我們來優化封裝一下:

    public static class DynamicExtention     {        public static IQueryable<T> Where<T>(this IQueryable<T> query, Filter[] filters)        {            var param = DynamicLinq.CreateLambdaParam<T>("c");            Expression body = Expression.Constant(true); //初始默認一個true            foreach (var filter in filters)            {                body = body.AndAlso(param.GenerateBody<T>(filter)); //這里可以根據需要自由組合            }            var lambda = param.GenerateTypeLambda<T>(body); //最終組成lambda            return query.Where(lambda);        }    }

    最后看看我們客戶端的調用:

 //模擬過濾對象            var filters = new Filter[]            {                new Filter {Key = "UserName", Value = "yubaolee", Contract = "like"},                new Filter {Key = "UserType", Value = "administrator", Contract = "="}            };            var users = _context.UserInfoes.Where(filters);  //得到最終結果            Console.Read();

    代碼如此的干凈整潔。而且因為擴展的Where語句是基于泛型的,所以無論你的EF集合是哪種DbSet,都可以直接拿來使用。如果再把過濾類Filter功能深化,擴展成樹狀結構,那么可以實現種組合查詢。哪怕是聯表查詢也不在話下。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲香蕉av在线一区二区三区| 国产午夜精品全部视频播放| 538国产精品一区二区免费视频| 欧美一区二区三区四区在线| 国产欧美日韩综合精品| 色综合影院在线| 日韩大片免费观看视频播放| 日韩影视在线观看| 亚洲v日韩v综合v精品v| 九九精品视频在线观看| 国产精品麻豆va在线播放| 韩曰欧美视频免费观看| 在线观看国产精品91| 狠狠躁夜夜躁人人爽天天天天97| 精品高清美女精品国产区| 日韩美女主播视频| 国产亚洲成av人片在线观看桃| 91久久久久久久久久| 国产精品电影一区| 亚洲国产91精品在线观看| 国产精品96久久久久久| 精品国产依人香蕉在线精品| 91干在线观看| 亚洲精品v欧美精品v日韩精品| 亚洲电影免费观看高清完整版| 日韩精品视频观看| 欧美国产第一页| 精品无人国产偷自产在线| 久久久久国产精品一区| 日产精品99久久久久久| 91热福利电影| 97精品国产91久久久久久| 中文字幕无线精品亚洲乱码一区| 91老司机在线| 亚洲春色另类小说| 欧美成人免费观看| 久久久久久成人精品| 日本一区二三区好的精华液| 69久久夜色精品国产69乱青草| 中文字幕亚洲欧美在线| 国内揄拍国内精品| 亚洲国产天堂久久综合| 亚洲国内精品在线| 亚洲自拍偷拍福利| 欧美激情国产高清| 国产精品视频成人| 国产亚洲精品美女久久久| 亚洲一区二区三区四区在线播放| 欧美午夜精品久久久久久久| 国产精品久久久久久av| 色偷偷888欧美精品久久久| 国产视频亚洲精品| 亚洲日本成人女熟在线观看| 欧美精品国产精品日韩精品| 日韩激情av在线免费观看| 欧美国产日韩免费| 欧美精品免费在线| 精品在线观看国产| 国产精品福利无圣光在线一区| 欧洲中文字幕国产精品| 国产精自产拍久久久久久| 欧美黑人视频一区| 91久久精品美女高潮| 亚洲码在线观看| 55夜色66夜色国产精品视频| 亚洲日本中文字幕免费在线不卡| 日韩在线观看免费全集电视剧网站| 国产精品av电影| 日韩在线观看免费av| 51精品国产黑色丝袜高跟鞋| 国产精品视频中文字幕91| 日韩中文在线中文网在线观看| 亚洲美女又黄又爽在线观看| 人体精品一二三区| 日韩欧美中文免费| 萌白酱国产一区二区| 欧美国产第一页| 亚洲高清福利视频| 日韩电影免费观看中文字幕| 91亚洲精品在线| xxxx性欧美| 国产精品久久久久免费a∨大胸| 日韩av在线看| 久久九九国产精品怡红院| 欧美精品999| 国模视频一区二区三区| 欧美人与物videos| 久久久亚洲国产| 77777少妇光屁股久久一区| 国产欧美日韩亚洲精品| 97在线观看免费高清| 亚洲精品国产精品乱码不99按摩| 国产mv免费观看入口亚洲| 欧美亚洲一区在线| 日韩欧美成人区| 亚洲精品永久免费| 日韩在线精品视频| 欧美性高跟鞋xxxxhd| 成人xxxxx| 日韩欧美在线视频观看| 日韩av免费一区| 2019中文字幕在线观看| 成人性生交大片免费观看嘿嘿视频| 久久久亚洲影院你懂的| 精品动漫一区二区三区| 亚洲精品电影网在线观看| 美女av一区二区| 一区二区三区四区视频| 在线亚洲午夜片av大片| 亚洲一区免费网站| 成人激情视频在线观看| 国产成人在线亚洲欧美| 国产精品自拍偷拍视频| 精品成人国产在线观看男人呻吟| 国产一区二区三区在线| 国产成人啪精品视频免费网| 国产精品九九九| 国产精品一区二区久久久| 日韩国产在线看| 久久久91精品国产一区不卡| 一夜七次郎国产精品亚洲| 国产一区二区三区网站| 狠狠色香婷婷久久亚洲精品| 97福利一区二区| 亚洲高清免费观看高清完整版| 成人h片在线播放免费网站| 欧美在线性爱视频| 亚洲精品影视在线观看| 清纯唯美日韩制服另类| 45www国产精品网站| 操日韩av在线电影| 精品视频久久久| 亚洲综合中文字幕68页| 91九色国产视频| 久久久久久97| 亚洲理论片在线观看| 久久亚洲私人国产精品va| 欧美黑人一级爽快片淫片高清| 亚洲欧美日韩成人| 久久精品国产欧美激情| 国产精品av在线播放| 欧美日韩国产中字| 欧美大片欧美激情性色a∨久久| 亚洲日本欧美中文幕| 亚洲国产精品专区久久| 日韩最新免费不卡| 亚洲欧美国产va在线影院| 亚洲成人aaa| 一区二区亚洲欧洲国产日韩| 7777精品视频| 精品久久久久久久大神国产| 亚洲精品v天堂中文字幕| 精品视频在线导航| 日韩中文字幕网| 黄色精品在线看| 国产成人精品国内自产拍免费看| 国产精品欧美风情| 色哟哟亚洲精品一区二区| 国产成人免费av| 国产精品欧美在线| 国产精品视频免费在线| 亚洲欧美一区二区三区情侣bbw| 日韩欧美在线第一页| 在线观看中文字幕亚洲|