博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Expression进行查询拼接
阅读量:4316 次
发布时间:2019-06-06

本文共 6379 字,大约阅读时间需要 21 分钟。

 

http://www.albahari.com/nutshell/linqkit.aspx

 

 

 

public
IQueryable<BBS_Theme> GetListPage(
int
PageSize,
int
PageIndex, NameValueCollection nvcParamWhere, NameValueCollection nvcorderby,
ref
int
AllCount)
      
{
          
#region where
          
var searchPredicate = PredicateExtensions.True<BBS_Theme>();
          
if
(nvcParamWhere !=
null
)
          
{
              
foreach
(
string
key
in
nvcParamWhere)
              
{
                  
string
condition =
string
.Empty;
                  
switch
(key)
                  
{
                      
#region
                      
case
"ID"
:
                          
condition = nvcParamWhere[key];
                          
searchPredicate = searchPredicate.And(u => u.ID.Equals(condition));
                          
break
;
                      
case
"LableID"
:
                          
condition = nvcParamWhere[key];
                          
searchPredicate = searchPredicate.And(u => u.LableID.Equals(condition));
                          
break
;
 
           
                       
                      
default
:
                          
break
;
 
                      
#endregion
                  
}
              
}
          
}
          
#endregion
           
          
#region queryable
          
var linq = (from a
in
db.BBS_Theme
                      
select a)
                      
.Where(searchPredicate);
          
#endregion
           
          
#region orderby
          
if
(nvcorderby !=
null
)
          
{
              
foreach
(
string
key
in
nvcorderby)
              
{
                  
string
condition =
string
.Empty;
 
                  
switch
(key)
                  
{
                      
case
"ID"
:
                          
condition = nvcorderby[key];
                          
if
(
bool
.Parse(condition))
                          
{
                              
linq = linq.OrderBy(o=>o.ID);
                          
}
                          
else
                          
{
                              
linq = linq.OrderByDescending(o => o.ID);
                          
}
                          
break
;
                      
//........省略n个case
                       
                      
default
:
                          
break
;
 
                  
}
              
}
          
}
          
#endregion
           
          
AllCount = linq.Count();
          
linq = linq.Skip(PageSize * (PageIndex - 1)).Take(PageSize);
          
return
linq;
      
}
 

LINQ动态组合查询PredicateExtensions讲解

在LINQ动态组合查询中我留下了一个问题就是PredicateExtensions。在这里很简单不需要什么多的基础只要比会And、Or逻辑运算数学知识就够了。

先贴上代码好分析:

 

代码
public
 
static
 
class
 PredicateExtensions
    {
       
public
 
static
 Expression
<
Func
<
T, 
bool
>>
 True
<
T
>
() { 
return
 f 
=>
 
true
; }
       
public
 
static
 Expression
<
Func
<
T, 
bool
>>
 False
<
T
>
() { 
return
 f 
=>
 
false
; }
       
public
 
static
 Expression
<
Func
<
T, 
bool
>>
 Or
<
T
>
(
this
 Expression
<
Func
<
T, 
bool
>>
 expression1, 
           Expression
<
Func
<
T, 
bool
>>
 expression2)
        {
            var invokedExpression 
=
 Expression.Invoke(expression2, expression1.Parameters
                    .Cast
<
Expression
>
());
           
return
 Expression.Lambda
<
Func
<
T, 
bool
>>
(Expression.Or(expression1.Body, invokedExpression),
            expression1.Parameters);
        }
       
public
 
static
 Expression
<
Func
<
T, 
bool
>>
 And
<
T
>
(
this
 Expression
<
Func
<
T, 
bool
>>
 expression1, 
              Expression
<
Func
<
T, 
bool
>>
 expression2)
        {
            var invokedExpression 
=
 Expression.Invoke(expression2, expression1.Parameters
                 .Cast
<
Expression
>
());
           
return
 Expression.Lambda
<
Func
<
T, 
bool
>>
(Expression.And(expression1.Body, 
                   invokedExpression), expression1.Parameters);
        }
    }

 

 

      在其中只有四个方法,True、False、Or、And,一看大家就知道这里是对逻辑运算操作。其中True、False是对表达式进行初始化,在我没 有看见这个类之前我用的是null,用null这要在没有And,Or逻辑操作时进行Null判断,如果null则返回后一个表达式。而在这里有了 true,fakse这相当于初始化了一个表达式,就不用再那么麻烦了。

    True、False的初始化有一个规则就是不能影响我们的正常表达式.在我们刚学语言的时候就有:逻辑与一假为假,逻辑或一真为真,那这句就可以运用于我们的这两表达式的初始化了。当我们在True、False初始化表达式和后便连接的表达式逻辑运算为And时候,我们就该用True,这么这个逻辑条件的真假取决于我们的后面表达式(逻辑与一假为假,一真那么还不确定),是不是没有影响我们的正常表达式?同理逻辑运算为Or时候,就该用False(逻辑或一真为真,一假也不确定,就取决于另一个表达式)。是不是很简单,还是那句话,我这种鼠辈估计很难想到,是应试教育禁锢了我们的思维啊!

      And、Or这是表达式逻辑运算连接,那主体为取出左边表达式body Invoke了再与右边表达式连接返回。

    为了验证我的结论,我们做几个小测试(这里为了方便改为了控制台程序):

测试1:True and连接;

 

代码
public
 
static
 
void
 Test1()
        {
            DbDataContext db 
=
 
new
 DbDataContext();
            Expression
<
Func
<
TemplateDocument, 
bool
>>
 expressleft 
=
 
                                PredicateExtensions.True
<
TemplateDocument
>
();
            expressleft 
=
 expressleft.And(t 
=>
 t.CategoriesID 
>
 
3
);
            Expression
<
Func
<
TemplateDocument, 
bool
>>
 expressright 
=
 
                                PredicateExtensions.True
<
TemplateDocument
>
();
            expressright 
=
 expressright.And(t 
=>
 t.CategoriesID 
<
 
5
);
          expressleft
=
  expressleft.Or(expressright);
          var sql 
=
 db.GetCommand(db.TemplateDocument.Where(expressleft).Select(t 
=>
 
new
 { 
                           t.TemplateID, t.TemplateName, t.CategoriesID })).CommandText;
            Console.WriteLine(sql);
        }

 

 

输出sql:

 

SELECT
 
[
t0
]
.
[
TemplateID
]
[
t0
]
.
[
TemplateName
]
[
t0
]
.
[
CategoriesID
]
 
FROM
 
[
dbo
]
.
[
TemplateDocument
]
 
AS
 
[
t0
]
 
WHERE
 (
[
t0
]
.
[
CategoriesID
]
 
>
 
@p0
OR
 (
[
t0
]
.
[
CategoriesID
]
 
<
 
@p1
)

 

 

不知你发现没有Linq表达式已经把True条件智能的去掉了,(True&&XX1)||(True&&XX2) = XX1||XX2。按照上面的说法,那我们把第一个条件改为False 的Or连接也应该一样,测试一下:

测试2

代码
public
 
static
 
void
 Test2()
        {
            DbDataContext db 
=
 
new
 DbDataContext();
            Expression
<
Func
<
TemplateDocument, 
bool
>>
 expressleft 
=
 
                             PredicateExtensions.False
<
TemplateDocument
>
();
//
上例True该为False
            expressleft 
=
 expressleft.Or(t 
=>
 t.CategoriesID 
>
 
3
);
//
上例And该为Or
            Expression
<
Func
<
TemplateDocument, 
bool
>>
 expressright 
=
 
                              PredicateExtensions.False
<
TemplateDocument
>
();
                         
//
上例True该为False
            expressright 
=
 expressright.Or(t 
=>
 t.CategoriesID 
<
 
5
);
                         
//
上例And该为Or
            expressleft 
=
 expressleft.Or(expressright);
            var sql 
=
 db.GetCommand(db.TemplateDocument.Where(expressleft).Select(t 
=>
 
new
 { 
                         t.TemplateID, t.TemplateName, t.CategoriesID })).CommandText;
            Console.WriteLine(sql);
        }

 

输出sql

SELECT
 
[
t0
]
.
[
TemplateID
]
[
t0
]
.
[
TemplateName
]
[
t0
]
.
[
CategoriesID
]
 
FROM
 
[
dbo
]
.
[
TemplateDocument
]
 
AS
 
[
t0
]
WHERE
 (
[
t0
]
.
[
CategoriesID
]
 
>
 
@p0
OR
 (
[
t0
]
.
[
CategoriesID
]
 
<
 
@p1
)

 

和上例输出了sql完全一样,,(False||XX1)||(False||XX2) = XX1||XX2。那我们改变用法将True或Or连接呢?

测试3:

代码
public
 
static
 
void
 Test3()
        {
            DbDataContext db 
=
 
new
 DbDataContext();
            Expression
<
Func
<
TemplateDocument, 
bool
>>
 expressleft 
=
                                 PredicateExtensions.True
<
TemplateDocument
>
();
            expressleft 
=
 expressleft.Or(t 
=>
 t.CategoriesID 
>
 
3
);
            Expression
<
Func
<
TemplateDocument, 
bool
>>
 expressright 
=
 
                PredicateExtensions.False
<
TemplateDocument
>
();
                                    expressright 
=
 expressright.Or(t 
=>
 t.CategoriesID 
<
 
5
);
            expressleft 
=
 expressleft.And(expressright);
            var sql 
=
 db.GetCommand(db.TemplateDocument.Where(expressleft).Select(t 
=>
 
new
 { 
                                    t.TemplateID, t.TemplateName, t.CategoriesID })).CommandText;
            Console.WriteLine(sql);
        }

 

输出sql:

SELECT
 
[
t0
]
.
[
TemplateID
]
[
t0
]
.
[
TemplateName
]
[
t0
]
.
[
CategoriesID
]
 
FROM
 
[
dbo
]
.
[
TemplateDocument
]
 
AS
 
[
t0
]
 
WHERE
 
[
t0
]
.
[
CategoriesID
]
 
<
 
@p0
 

 

恩 只有一个表达式了,当然了啊,你第一个表达式是(True||XX1)&&(False||XX2) = True&&XX2=XX2.做了这个测试,我真的很佩服微软,在代码中能够这么智能判断。索性把条件完全弄掉,我们把中间的And改为 Or:(True||XX1)||(False||XX2) = True||XX2=True。这个就自己测试了你将看不到where条件了。 肖坤在Linq动态查询与模糊查询(带源码示例)中给出了一个结果总结.

  1:构造函数使用True时:单个AND有效,多个AND有效;单个OR无效,多个OR无效;混合时写在AND后的OR有效

  2:构造函数使用False时:单个AND无效,多个AND无效;单个OR有效,多个OR有效;混合时写在OR后面的AND有效

我们来验证验证:

1构造函数使用True时:

(1):单个AND有效,多个AND有效,当然了True&&XX=XX

(2):单个OR无效,多个OR无效:True || XX=True所以无效。

(3):混合时写在AND后的OR有效:(True&&XX)||XX1=XX||XX1有效,(True||XX)&& amp;XX1=True&&XX1=XX1,肖博前辈说的无效(相对于我们需要的表达式无效,其实还是有效) (True||XX)||XX1=True||XX1=True(这里你不会看见where条件)。

2:构造函数使用False时:

  和True情况一样,我就不去推导了,偷个懒。

以上全是个人意见,如果有什么不对了请指导,更正。

 

 

 

转载于:https://www.cnblogs.com/shiningrise/archive/2013/03/28/2986836.html

你可能感兴趣的文章
转 sql删除重复记录
查看>>
Yum数据库错误
查看>>
HDOJ树形DP专题之考研路茫茫——空调教室
查看>>
《结对-蓝牙考勤系统-测试过程》
查看>>
PAT 1034. Head of a Gang
查看>>
微信分享
查看>>
《数据结构》第1章:绪论
查看>>
基于域名的虚拟主机(最常用)
查看>>
第八讲 shiro 整合 ssm
查看>>
Lucene
查看>>
[LeetCode] 83. Remove Duplicates from Sorted List 移除有序链表中的重复项
查看>>
CNN反卷积理解
查看>>
chrome 中firstChild老是出错
查看>>
Java 7 新的 try-with-resources 语句,自动资源释放
查看>>
封装一个函数, 查看数字在数组中是否出现过, 如果出现过就返回数字在数组中的位置,没有出现过返回-1;...
查看>>
查看用户登录情况
查看>>
双栈排序-NOIP2008T4
查看>>
C#多线程及GDI(Day 23)
查看>>
static关键字
查看>>
Oracle the network adapter could not establish the connection
查看>>