linq to sql 中,如何解决多条件查询问题,答案,用表达式树! (下)
程序员文章站
2024-03-06 19:46:02
如何从真正意义上做到延迟加载,即一次只从数据库中取我们需要的用到的那部分数据呢.通过研究,有了下面的方法: 首先,我们要新建一个静态类,用于存放多条件组合查询的各种组合,比...
如何从真正意义上做到延迟加载,即一次只从数据库中取我们需要的用到的那部分数据呢.通过研究,有了下面的方法:
首先,我们要新建一个静态类,用于存放多条件组合查询的各种组合,比如or,and这些等等.代码如下:
using system.linq.expressions;
public static class predicateextensionses
{
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>> exp_flow, expression<func<t, bool>> expression2)
{
var invokedexpression = system.linq.expressions.expression.invoke(expression2, exp_flow.parameters.cast<system.linq.expressions.expression>());
return system.linq.expressions.expression.lambda<func<t, bool>>(system.linq.expressions.expression.or(exp_flow.body, invokedexpression), exp_flow.parameters);
}
public static expression<func<t, bool>> and<t>(this expression<func<t, bool>> exp_flow, expression<func<t, bool>> expression2)
{
var invokedexpression = system.linq.expressions.expression.invoke(expression2, exp_flow.parameters.cast<system.linq.expressions.expression>());
return system.linq.expressions.expression.lambda<func<t, bool>>(system.linq.expressions.expression.and(exp_flow.body, invokedexpression), exp_flow.parameters);
}
}
第一步工作完成后,我们就可以从具体应用层面上来调用这种组合了,此处,我们仍以feedback表对象为例,表示层调用代码如下:
我仅列举核心代码,注意:pagenavigator1是我页面的分页控件.
分页代码:
private void listdatabind(int pageindex)
{
int rowcount = 0;
int pagecount = 0;
int pagesize = 30;
expression<func<feedback, bool>> expr = predicateextensionses.true<feedback>();
getcondition(ref expr);
var hs = from h in hm.allfeedbacks.where(expr) select h;//延迟加载,数据库没有任何操作
if (pageindex == 1)//如果是第一次取数据,需要获取符合条件的总记录条数
{
rowcount = hs.count();//数据库进行一次count操作
}
else//之后的记录条数,从分页控件持久态的属性中获取,省去一次count查询
{
rowcount = pagenavigator1.recordcount;
}
pagecount = rowcount > pagesize ? convert.toint32((rowcount - 1) / pagesize) + 1 : 1;//通用分页算法
if (pageindex > pagecount)
{
pageindex = pagecount;
}
var pagedata = hs.skip(pagesize * (pageindex - 1)).take(pagesize);//这里也是延迟加载,数据库此时不操作
feedbackmanagelist.datasource = pagedata;//这里才正式加载数据,仅仅向数据库发出请求30条记录sql
feedbackmanagelist.databind();
pagenavigator1.recordcount = rowcount;// 给分页控件一些数据
pagenavigator1.pagecount = pagecount;//给分页控件一些数据
pagenavigator1.pageindex = pageindex;//给分页控件一些数据
}
接下来是关键部分,组合条件,注意这里,我们用到了第一步中定义好的组合类:
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给我们带来便利的同时,也埋下许多的隐患,比如给像我这样的偷懒者更多便利,但却不去思考,往往一不小心就加载了数据,造成了资源的浪费.在享受这些便利的同时,应注意适时地进行研究,以让它们更好地为我们服务.
首先,我们要新建一个静态类,用于存放多条件组合查询的各种组合,比如or,and这些等等.代码如下:
复制代码 代码如下:
using system.linq.expressions;
public static class predicateextensionses
{
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>> exp_flow, expression<func<t, bool>> expression2)
{
var invokedexpression = system.linq.expressions.expression.invoke(expression2, exp_flow.parameters.cast<system.linq.expressions.expression>());
return system.linq.expressions.expression.lambda<func<t, bool>>(system.linq.expressions.expression.or(exp_flow.body, invokedexpression), exp_flow.parameters);
}
public static expression<func<t, bool>> and<t>(this expression<func<t, bool>> exp_flow, expression<func<t, bool>> expression2)
{
var invokedexpression = system.linq.expressions.expression.invoke(expression2, exp_flow.parameters.cast<system.linq.expressions.expression>());
return system.linq.expressions.expression.lambda<func<t, bool>>(system.linq.expressions.expression.and(exp_flow.body, invokedexpression), exp_flow.parameters);
}
}
第一步工作完成后,我们就可以从具体应用层面上来调用这种组合了,此处,我们仍以feedback表对象为例,表示层调用代码如下:
我仅列举核心代码,注意:pagenavigator1是我页面的分页控件.
分页代码:
复制代码 代码如下:
private void listdatabind(int pageindex)
{
int rowcount = 0;
int pagecount = 0;
int pagesize = 30;
expression<func<feedback, bool>> expr = predicateextensionses.true<feedback>();
getcondition(ref expr);
var hs = from h in hm.allfeedbacks.where(expr) select h;//延迟加载,数据库没有任何操作
if (pageindex == 1)//如果是第一次取数据,需要获取符合条件的总记录条数
{
rowcount = hs.count();//数据库进行一次count操作
}
else//之后的记录条数,从分页控件持久态的属性中获取,省去一次count查询
{
rowcount = pagenavigator1.recordcount;
}
pagecount = rowcount > pagesize ? convert.toint32((rowcount - 1) / pagesize) + 1 : 1;//通用分页算法
if (pageindex > pagecount)
{
pageindex = pagecount;
}
var pagedata = hs.skip(pagesize * (pageindex - 1)).take(pagesize);//这里也是延迟加载,数据库此时不操作
feedbackmanagelist.datasource = pagedata;//这里才正式加载数据,仅仅向数据库发出请求30条记录sql
feedbackmanagelist.databind();
pagenavigator1.recordcount = rowcount;// 给分页控件一些数据
pagenavigator1.pagecount = pagecount;//给分页控件一些数据
pagenavigator1.pageindex = pageindex;//给分页控件一些数据
}
接下来是关键部分,组合条件,注意这里,我们用到了第一步中定义好的组合类:
复制代码 代码如下:
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给我们带来便利的同时,也埋下许多的隐患,比如给像我这样的偷懒者更多便利,但却不去思考,往往一不小心就加载了数据,造成了资源的浪费.在享受这些便利的同时,应注意适时地进行研究,以让它们更好地为我们服务.