linq to sql 中,如何解决多条件查询问题,答案,用表达式树! (下)

上一篇中,我们做了基于linq to sql 的多条件组合查询,但通过监视数据库发现,这样做的成本比较高,每次都要取出全部的数据到内存进行筛选.如何从真正意义上做到延迟加载,即一次只从数据库中取我们需要的用到的那部分数据呢.通过研究,有了下面的方法:

首先,我们要新建一个静态类,用于存放多条件组合查询的各种组合,比如or,And这些等等.代码如下:

代码
 1  using  System.Linq.Expressions;
 2 
 3  public   static   class  PredicateExtensionses
 4  {
 5           public   static  Expression < Func < T,  bool >>  True < T > () {  return  f  =>   true ; }
 6 
 7           public   static  Expression < Func < T,  bool >>  False < T > () {  return  f  =>   false ; }
 8 
 9           public   static  Expression < Func < T,  bool >>  Or < T > ( this  Expression < Func < T,  bool >>  exp_flow, Expression < Func < T,  bool >>  expression2)
10          {
11 
12              var invokedExpression  =  System.Linq.Expressions.Expression.Invoke(expression2, exp_flow.Parameters.Cast < System.Linq.Expressions.Expression > ());
13 
14               return  System.Linq.Expressions.Expression.Lambda < Func < T,  bool >> (System.Linq.Expressions.Expression.Or(exp_flow.Body, invokedExpression), exp_flow.Parameters);
15 
16          }
17           public   static  Expression < Func < T,  bool >>  And < T > ( this  Expression < Func < T,  bool >>  exp_flow, Expression < Func < T,  bool >>  expression2)
18          {
19 
20              var invokedExpression  =  System.Linq.Expressions.Expression.Invoke(expression2, exp_flow.Parameters.Cast < System.Linq.Expressions.Expression > ());
21 
22               return  System.Linq.Expressions.Expression.Lambda < Func < T,  bool >> (System.Linq.Expressions.Expression.And(exp_flow.Body, invokedExpression), exp_flow.Parameters);
23 
24          }
25 
26      }

 

 

第一步工作完成后,我们就可以从具体应用层面上来调用这种组合了,此处,我们仍以FeedBack表对象为例,表示层调用代码如下:

我仅列举核心代码,注意:PageNavigator1是我页面的分页控件.

分页代码:

 

 

代码
 1           private   void  ListDataBind( int  pageIndex)
 2          {  
 3               int  rowCount  =   0 ;
 4               int  pageCount  =   0 ;
 5               int  pageSize  =   30 ;
 6              Expression < Func < FeedBack,  bool >>  expr  =  PredicateExtensionses.True < FeedBack > ();
 7              GetCondition( ref  expr);
 8              var hs  =  from h  in  hm.AllFeedBacks.Where(expr) select h;// 延迟加载,数据库没有任何操作
 9               if  (pageIndex  ==   1 )// 如果是第一次取数据,需要获取符合条件的总记录条数
10              {  
11                  rowCount  =  hs.Count();// 数据库进行一次Count操作
12              }
13               else//之后的记录条数,从分页控件持久态的属性中获取,省去一次Count查询
14              {
15                  rowCount  =  PageNavigator1.RecordCount;
16              }
17              pageCount  =  rowCount  >  pageSize  ?  Convert.ToInt32((rowCount  -   1 /  pageSize)  +   1  :  1 ;// 通用分页算法
18               if  (pageIndex  >  pageCount)
19              {
20                  pageIndex  =  pageCount;
21              }
22              var pageData  =  hs.Skip(pageSize  *  (pageIndex  -   1 )).Take(pageSize);// 这里也是延迟加载,数据库此时不操作
23              FeedBackManageList.DataSource  =  pageData;// 这里才正式加载数据,仅仅向数据库发出请求30条记录SQL
24              FeedBackManageList.DataBind();
25               PageNavigator1.RecordCount  =  rowCount;//给分页控件一些数据
26               PageNavigator1.PageCount  =  pageCount;//给分页控件一些数据
27               PageNavigator1.PageIndex  =  pageIndex;//给分页控件一些数据
28          }

 

接下来是关键部分,组合条件,注意这里,我们用到了第一步中定义好的组合类:

 

代码
         private   void  GetCondition( ref  Expression < Func < FeedBack,  bool >>  expr) {
            
int  isLock  =  Int32.Parse(ddlIsLock.SelectedValue);
            
if  (isLock  >   - 1 )
            {
                expr 
=  expr. And (c  =>  (c.IsLock  ==  isLock));//一次组合
            }
            
string  keyword  =  tbxKeyword.Text.FilterInjectStr();
            
if  ( ! keyword.IsNullOrEmpty())
            {
                expr 
=  expr. And (c  =>  (c.HotelName.IndexOf(keyword)  >   - 1 )); //二次组合
            }
        } 

 

 

 

到此,我们已经完成了linq to Sql多条件组合查询,并且对数据库的请求做到最小化.

另外,要特别说明的是:对数据源的任何操作,最好用延迟加载,否则,将有可能加载全部数据,

例如,我们写这样的代码:List<FeedBack> fbs = hm.AllFeedBacks.Where(c=>c.Id > 1000).ToList();这样消耗将会非常严重!因为这里会将FeedBack表所有数据全部加载进来!所以,千万要慎用这种写法.

 

总结:微软的linq to sql给我们带来便利的同时,也埋下许多的隐患,比如给像我这样的偷懒者更多便利,但却不去思考,往往一不小心就加载了数据,造成了资源的浪费.在享受这些便利的同时,应注意适时地进行研究,以让它们更好地为我们服务.

你可能感兴趣的:(LINQ)