国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

Linq動態(tài)查詢簡易解決之道(原創(chuàng))

2019-11-17 03:09:39
字體:
來源:轉載
供稿:網(wǎng)友

Linq動態(tài)查詢簡易解決之道(原創(chuàng))

 因為項目需要使用Linq來查詢數(shù)據(jù),但是在多條件查詢時,需要使用一大堆if(...!=string.empty)等判斷條件感覺不是很優(yōu)雅。網(wǎng)上搜索以下,大概找到了兩種辦法,一種是老外寫的一個類,感覺用著麻煩;還有就是提供一擴展個方法,參數(shù)為某個類型,當調用該方法時,用反射去遍歷這個類型的屬性,再拿動態(tài)查詢參數(shù)和屬性值去比較,然后構建動態(tài)lambda表達式,這個也有缺陷,就是需要遍歷類型的所有屬性,而且構建lambda表達式只能構建==類型表達式,有局限性。所以自己琢磨了一個辦法,調用時只需一行代碼,lambda表達式可以隨意構建,現(xiàn)在進入主題。  假設有一個類型Employee,并且該類型有集合employeeList,有這樣一個基于IEnumerable<T>類型的擴展方法Wheres(稍后介紹),那怎樣用一行代碼employeeList.Wheres(o => o.Name == "a" && o.Salary > 5000 && o.InDate >= DateTime.Now && o.Address.Contains("北京"))去實現(xiàn)如下一堆代碼:

    if (!string.IsNullOrEmpty(name)) { employeeList.Where(o => o.Name == name); } if (salary != null)參數(shù)設置為可空 { employeeList.Where(o => o.Name == name); } if (inDate != null) { employeeList.Where(o => o.InDate>=inDate); } if (!string.IsNullOrEmpty(address)) { employeeList.Where(o => o.Address.Contains("北京")); }

  因為Linq Lambda表達式在運行的時候會被解析成一棵表達式的二叉樹,這棵樹只允許左邊的子節(jié)點存在BinaryEx

我們只需找出紅色節(jié)點,然后得到藍色節(jié)點的值,然后去構建動態(tài)Lambda表達式就可以了,所以的獲取節(jié)點的方法如下:

 /// <summary>        /// 分解表達式樹        /// </summary>        /// <param name="tree"></param>        /// <returns></returns>        private static Stack<Expression> DivideBinaryExpression(Expression expression)        {            Stack<Expression> stack = new Stack<Expression>();            if (expression.NodeType != ExpressionType.AndAlso) //為了簡化調用代碼,只允許根節(jié)點為&&            {                stack.Push(expression);            }            else            {                BinaryExpression tree = expression as BinaryExpression;                while (tree != null && tree.NodeType == ExpressionType.AndAlso)                {                    stack.Push(tree.Right);                    if (tree.Left.NodeType != ExpressionType.AndAlso)                    {                        stack.Push(tree.Left);                    }                    tree = tree.Left as BinaryExpression;//循環(huán)遍歷表達式                }            }            return stack;        }
View Code

然后再根據(jù)得到的節(jié)點去動態(tài)構建Lambda表達式,方法如下:

/// <summary>        /// 多where子句查詢        /// </summary>        /// <typeparam name="TSource">實體類型</typeparam>        /// <typeparam name="TResult">Expression的返回類型</typeparam>        /// <param name="t">實體集合</param>        /// <param name="expression">表達式</param>        /// <returns>實體集合</returns>        public static IEnumerable<TSource> Wheres<TSource>(this IEnumerable<TSource> t, Expression<Func<TSource, bool>> expression)        {            foreach (Expression e in DivideBinaryExpression(expression.Body))            {                object expressionValue = null;                if ((e as BinaryExpression) != null)                {                    BinaryExpression be = e as BinaryExpression;                    expressionValue = LambdaExpression.Lambda(be.Right).Compile().DynamicInvoke();                }                else //為了處理像o.Address.Contains("北京")這樣的特殊節(jié)點                {                    MethodCallExpression mce = e as MethodCallExpression;                    expressionValue = LambdaExpression.Lambda(mce.Arguments[0]).Compile().DynamicInvoke();                }                if (expressionValue != null)                {                    if (!string.IsNullOrEmpty(expressionValue.ToString()))                        t = t.Where(Expression.Lambda<Func<TSource, bool>>(e, expression.Parameters).Compile());                }            }            return t;        }
View Code

在調用的時候只需像上面提到的一行代碼就夠了,雖然不是很完善,但至少能解決90%以上的需求.


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 西乌珠穆沁旗| 宜昌市| 耿马| 光泽县| 秦安县| 北京市| 大化| 宜君县| 洪江市| 青浦区| 娱乐| 乐山市| 衡阳市| 盈江县| 凤城市| 黔江区| 玛纳斯县| 洪江市| 万源市| 齐齐哈尔市| 简阳市| 阳西县| 兴宁市| 金川县| 大城县| 浠水县| 湘潭县| 城市| 诏安县| 陕西省| 仁化县| 通道| 全椒县| 洛隆县| 瑞金市| 威宁| 光山县| 聊城市| 高雄市| 淄博市| 鄂尔多斯市|