日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Linq to Sql : 动态构造Expression进行动态查询

發(fā)布時(shí)間:2025/4/16 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linq to Sql : 动态构造Expression进行动态查询 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

??? 前一篇在介紹動(dòng)態(tài)查詢時(shí),提到一個(gè)問題:如何根據(jù)用戶的輸入條件,動(dòng)態(tài)構(gòu)造這個(gè)過濾條件表達(dá)式呢?
Expression<Func<ProductExt, bool>> predicate t => t.ProductName.Contains("che") && t.UnitPrice >= 22;

??? 理想情況下,我希望可以像下面這樣來(lái)構(gòu)造predicate,這樣,我們就可以使用&、| 、&=、|=來(lái)任意拼接過濾條件了:

1: Expression<Func<ProductExt, bool>> predicate = null; 2: predicate (t => t.ProductName.Contains("che")) (t => t.UnitPrice >= 22);

??? 但是理想與現(xiàn)實(shí)之間,似乎總有不可逾越的鴻溝……

?

??? 前面的代碼中,我們總是要寫一常串Expression<Func<T, bool>>,寫得都有點(diǎn)兒煩了,我妄想自定義一個(gè)類型,這樣就不用每次都寫這么長(zhǎng)了,然后再針對(duì)這個(gè)自定義類型再進(jìn)行運(yùn)算符重載……然后我發(fā)現(xiàn),Expression<Delegate>是密封類型(sealed),不給重載,沒辦法,只好老老實(shí)實(shí)的寫,運(yùn)算符重載也泡湯了。

?

?? 無(wú)奈之下,只好實(shí)現(xiàn)了下面的這種方式,勉強(qiáng)湊合用著:

1: Expression<Func<, bool>> predicate = null; 2: predicate = predicate.AndAlso(p => p.CompanyName.Length > 2) 3: .OrElse((p) => p.ProductName.Contains("che")) 4: .AndAlso(( p) => p.UnitPrice >= 22);

??? 運(yùn)算得到的結(jié)果如下:p => (((p.CompanyName.Length > 2) || p.ProductName.Contains("che")) && (p.UnitPrice >= 22))

??? 有了這個(gè)OrElse和AndAlso擴(kuò)展,我們就可以對(duì)Expression<Func<T, bool>>為所欲為了……

??? 不過跟之前文章中提到的一樣,這里有個(gè)限制:雖然我們的Expression中,第一個(gè)可以凡泛型參數(shù)可以傳任意值(譬如傳ProductExt或Products或其他的,可以不必要求是同一種類型),但條件中用到的對(duì)象屬性(譬如CompanyName、ProductName、UnitPrice ),必須在T中存在同名屬性。

?

?2010-12-31更新:

?更新了ParameterConverter類,之前對(duì)二元運(yùn)算符的右側(cè)和方法參數(shù)直接求值的,所以不能處理Expression中含有&& 和 || 等二元運(yùn)算符、及方法參數(shù)中包含Expression參數(shù)(例如list.Contains(p.CompanyName))的情況;現(xiàn)在增加了參數(shù)訪問計(jì)數(shù),如果二元表達(dá)式&&和||、及方法的參數(shù)中不包含Expression參數(shù),則進(jìn)行求值,否則不求值。代碼如下:

?1?????public?class?ParameterConverter?:?ExpressionVisitor
?2?????{
?3?????????protected?LambdaExpression?SourceExpression?{?get;?set;?}
?4?????????protected?ParameterExpression?Parameter?{?get;?set;?}
?5?????????protected?bool?UseOuterParameter?=?false;
?6?
?7?????????public?ParameterConverter(LambdaExpression?expression)
?8?????????{
?9?????????????this.SourceExpression?=?(LambdaExpression)expression;
10?????????}
11?
12?????????public?ParameterConverter(LambdaExpression?expression,?ParameterExpression?parameter)?:?this(expression)
13?????????{
14?????????????this.Parameter?=?parameter;
15?????????????this.UseOuterParameter?=?true;
16?????????}
17?
18?????????public?LambdaExpression?Replace(Type?targetType)
19?????????{
20?????????????if?(this.SourceExpression?==?null)
21?????????????????return?null;
22?
23?????????????if?(!this.UseOuterParameter)
24?????????????????this.Parameter?=?Expression.Parameter(targetType,?this.SourceExpression.Parameters[0].Name);
25?
26?????????????Expression?body?=?this.Visit(this.SourceExpression.Body);
27?????????????this.SourceExpression?=?Expression.Lambda(body,?this.Parameter);
28?????????????return?this.SourceExpression;
29?????????}
30?
31?????????protected?override?Expression?VisitParameter(ParameterExpression?p)
32?????????{
33?????????????return?this.Parameter;
34?????????}
35?
36?????????protected?override?Expression?VisitMemberAccess(MemberExpression?m)
37?????????{
38?????????????Expression?exp?=?this.Visit(m.Expression);
39?????????????PropertyInfo?propertyInfo?=?m.Member?as?PropertyInfo;
40?????????????return?propertyInfo?==?null???m?:?Expression.Property(exp,?propertyInfo.Name);
41?????????}
42?
43?????????protected?override?Expression?VisitBinary(BinaryExpression?b)
44?????????{
45?????????????Expression?left?=?this.Visit(b.Left);
46?????????????Expression?right?=?Calc(b.Right);//對(duì)二元運(yùn)算符右邊的表達(dá)式進(jìn)行求值
47?????????????Expression?conversion?=?this.Visit(b.Conversion);
48?????????????if?(b.NodeType?==?ExpressionType.Coalesce?&&?b.Conversion?!=?null)
49?????????????????return?Expression.Coalesce(left,?right,?conversion?as?LambdaExpression);
50?????????????else
51?????????????????return?Expression.MakeBinary(b.NodeType,?left,?right,?b.IsLiftedToNull,?b.Method);
52?????????}
53?
54?????????protected?override?ReadOnlyCollection<Expression>?VisitExpressionList(
55?????????????????ReadOnlyCollection<Expression>?original)
56?????????{
57?????????????if?(original?==?null?||?original.Count?==?0)
58?????????????????return?original;
59?
60?????????????//對(duì)參數(shù)進(jìn)行求值運(yùn)算
61?????????????List<Expression>?list?=?new?List<Expression>();
62?????????????for?(int?i?=?0,?n?=?original.Count;?i?<?n;?i++)
63?????????????{
64?????????????????list.Add(Calc(original[i]));?//對(duì)調(diào)用函數(shù)的輸入?yún)?shù)進(jìn)行求值
65?????????????}
66?????????????return?list.AsReadOnly();
67?????????}
68?
69?????????private?static?Expression?Calc(Expression?e)
70?????????{
71?????????????LambdaExpression?lambda?=?Expression.Lambda(e);
72?????????????return?Expression.Constant(lambda.Compile().DynamicInvoke(null),?e.Type);
73?????????}
74?????}


?

? 最后,上代碼:LinqToSqlExtension

?博客園的文件貌似有緩存,刪掉重新上傳,總是覆蓋不了,只好單獨(dú)上傳了 ParameterConverter.rar

轉(zhuǎn)載于:https://www.cnblogs.com/happyhippy/archive/2010/01/28/1658410.html

總結(jié)

以上是生活随笔為你收集整理的Linq to Sql : 动态构造Expression进行动态查询的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。