zoukankan      html  css  js  c++  java
  • 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给我们带来便利的同时,也埋下许多的隐患,比如给像我这样的偷懒者更多便利,但却不去思考,往往一不小心就加载了数据,造成了资源的浪费.在享受这些便利的同时,应注意适时地进行研究,以让它们更好地为我们服务.

  • 相关阅读:
    Java多线程学习
    JAVA类的加载机制
    这四款也许是电脑录屏软件中免费、无广告且最实用的,程序员必备
    手机端没有好的录屏软件?地表最强移动端录屏软件了解一下?
    手把手教你 在Pytorch框架上部署和测试 关键点人脸检测项目DBFace,成功实现人脸检测效果
    520是秀恩爱吃狗粮,521才是真正的告白日,- Python告白神器用起来 !
    截图还在使用QQ的Ctrl + Alt + A 截图?还不会网页长截图?
    卷积神经网络之卷积操作,使用卷积运算实现图片边缘特征检测
    小白也能弄懂的卷积神经网络(Convolutional Neural Networks )
    官网安装Python包太慢?教你三种下载安装方式-PiP、conda、轮子,教你三种Pytorch的下载安装方式,保证你再也不用出现Error
  • 原文地址:https://www.cnblogs.com/baiyu/p/2094819.html
Copyright © 2011-2022 走看看