LINQ DYNAMIC SEARCH体会

 

1.     前言      

一直以来,ORM被认为是企业应用架构中不可或缺的一环,是面向对象程序设计的代表,是关系型数据库与程序对象连接桥梁。在众多的ORM开源框架中,Hibernate是最著名最耀眼的那个,我也曾在多个系统中都应用了Nhibernate。可惜的是,Nhibernate向下兼容性不好,2.0无法兼容1.1的应用,给我们项目组带来了困扰。数据库与对象的映射主流的方式包括两种:一种是xml,一种是Attribute反射。早期主流的是xml形式,个人认为xml文件太多,不便于管理,同时除了xml文件之外,还是需要建立Entity类,所以一直寻找一种比较简便的方法。后来我自己实现了后一种方式,不过是轻量级的,再后来linq出现了,其中linq2sql便是采用这种方式。

我们的目的是为了实现数据持久化,用什么框架都无所谓。为了以后升级的方便,所以我决定绑定微软这艘大船,采用linq

2.     Linq2sql

Linq是什么,园子里很多大牛都已经阐述的非常清楚了,我就不赘述了。我主要用到的是linq2sql,而最为常见的应用在园子里也是数不胜数,我主要介绍的是在实际应用经常用到的Dynamic Search动态查询。这将会用到微软提供的一个类库,在他提供的LinqSamples中,叫做Dynamic.cs

3.     动态查询

3.1.    like/in

linqlike通常用Contains来实现,示例如下

var query  =  from a  in  _ctx.A Where a.Name. Contains(condition) select a;
// 或者
var query 
=  _ctx.A.Where(a  =>  a.Name. Contains(condition));

 

而用Dynamic的语法如下

var query  =  from a  in  _ctx.A Where("Name. Contains( \"" + condition +"\")") ;
// 或者
var query  =  _ctx.A.Where("Name. Contains( \"" + condition +"\ ")" );

linqin通常也用Contains来实现,示例如下

var objIds  =   new   int []{ 1 , 3 , 5 };
var query 
=  from a  in  _ctx.A Where objIds. Contains(a.ObjId) select a;

 

这里如果aobjid字段为int型,则采用int数组,如果为string型,则采用string数组,以此类推。

而采用Dynamic就没有那么方便了,需要将数组拆分并组合成or语句,示例如下

var objIds  =   new   int []{ 1 , 3 , 5 };
StringBuilder sqlClause 
=   new  StringBuilder();
Foreach(
int  objId  in  objIds)
      sqlClause.Append(“ ObjId 
=  ” + objId + ” or ”);

if (sqlClause.Length  >   0 )
{
         
string  temp  =  sqlClause.ToString();
         temp 
=  temp.Substring( 0 , temp.LastIndexOf( " or " ));
         var query 
=  _ctx.A.Where(temp);
}

 

3.2.    复杂查询

通常情况下,由于用户输入的条件是未知的,所以查询时字段也是未知,如果还存在与其他表关联查询的话,则更为复杂。这种情况下,推荐使用Dynamic,示例如下

StringBuilder sqlClause = new StringBuilder();
if (condition.investNum > 0)
    sqlClause.Append(
" and Invest ="+ condition.investNum);


if  (condition.benefitNum  >   0 )
    sqlClause.Append(
"  and ContractBenefits = " +  condition.benefitNum);


if (condition.startTime != DateTime.MinValue)
     sqlClause.Append(
" and StartTime = DateTime(" + condition.startTime.Year + "," + condition.startTime.Month + "," + condition.startTime.Day + ")");

if (condition.endTime != DateTime.MinValue)
      sqlClause.Append(
" and EndTime =DateTime(" + condition.endTime.Year + "," + condition.endTime.Month + "," + condition.endTime.Day + ")");

if (!string.IsNullOrEmpty(condition.desc))
      sqlClause.Append(
" and Description.Contains("\""+condition.desc+"\"")");

var query 
= from a in _ctx.A.Where(sqlClause.ToString()) 
            join b 
in _ctx.B.Where(sqlClause.ToString())
            on a.ObjId equals b.AId
            select a;

//如果关联C查询

query = from a in query

        join c in _ctx.C.Where(condition)

        on a.ObjId equals c.AId

        select a;

 

在使用Dynamic是需要注意的是时间型,当数据采用时间型式,采用上述方案时,如果直接使用 endtime >= time的方式,Dynamic类则会抛出异常,认为数据类型匹配不上,所以在上述方案中,最好采用endtime >= DateTime(int年,int月,int)的方式。如果没有动态组装查询string,也可以采用如下方式

var query  =  from a  in  _ctx.A.Where(“EndTime  >=  @ 0 ”,time) select a;

 

      总的来说,绝大部分的动态查询(结合Intersect求交、Union求并等方法)用linq都能实现,笔者在项目中为了实现一个报表曾经实现过关联7张表左右的联合查询,关键看自己能否灵活运用linq的查询。

 

转载于:https://www.cnblogs.com/wangyub522/archive/2009/06/22/1508197.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值