• 软件测试技术
  • 软件测试博客
  • 软件测试视频
  • 开源软件测试技术
  • 软件测试论坛
  • 软件测试沙龙
  • 软件测试资料下载
  • 软件测试杂志
  • 软件测试人才招聘
    暂时没有公告

字号: | 推荐给好友 上一篇 | 下一篇

Linq To Sql进阶系列(七)动态查询续及CLR与SQL在某些细节上的差别

发布: 2008-5-07 13:46 | 作者: 网络转载 | 来源: 本站原创 | 查看: 179次 | 进入软件测试论坛讨论

领测软件测试网  在上面一篇文章Linq To Sql进阶系列(六)中,我们提到了使用object的动态查询。本文在上文的基础上,再做更加深入的引申。同时修正上文中一些不妥的地方。

  1, object的动态查询续
  首先要做的事情,就是将Find的函数改成扩展方法。扩展方法只能放在静态类里,而且它的第一个参数必须带this关键字。在上文中,作者留下了一个迷题。当需要or条件时,又该如何做呢?本文也将这个问题给出回答。但是对于动态Like的条件,笔者依然还没有找到一个较好的方法。为了增加or条件,函数的声明也再一次被改动。如下:
  public static IQueryable<TEntity> Find<TEntity>(this IQueryable<TEntity> source, TEntity obj, bool isAnd) where TEntity : class
  在上文中,我们还碰到了System.Nullable<int>此类类型不支持的问题。其实这个地方主要原因在于我们构造right端的 Expression Tree时,没有给它参数。那么这个问题通过Expression right = Expression.Constant(p.GetValue(obj, null), p.PropertyType); 可以得到修复。那整个函数修改后,如下:
public static IQueryable<TEntity> Find<TEntity>(this IQueryable<TEntity> source, TEntity obj, bool isAnd) where TEntity : class { if (source == null) throw new ArgumentNullException("Source can't be null!!"); //获得所有property的信息 PropertyInfo[] properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); Expression condition = null; //先构造了一个ParameterExpression对象,这里的c,就是Lambda表达中的参数。(c=>) //本变量被移出了foreach循环 ParameterExpression param = Expression.Parameter(typeof(TEntity), "c"); //遍历每个property foreach (PropertyInfo p in properties) { if (p != null) { Type t = p.PropertyType; //只支持value型和string型的影射 if (t.IsValueType || t == typeof(string)) { //如果不为null才算做条件 if (p.GetValue(obj, null) != null) { //SQL Server does not support comparison of TEXT, NTEXT, XML and IMAGE ,etc /**////Only support BigInt,Bit,Char,Decimal,Money,NChar,Real, ///Int,VarChar,SmallMoney,SmallInt,NVarChar,NVarChar(MAX),VarChar(MAX) Attribute attr = Attribute.GetCustomAttribute(p, typeof(ColumnAttribute)); if (attr != null) { string dbType = (attr as ColumnAttribute).DbType; if (dbType.Contains("Text") || dbType.Contains("NText") || dbType.Contains("Xml") || dbType.Contains("Image") || dbType.Contains("Binary") || dbType.Contains("DateTime") || dbType.Contains("sql_variant") || dbType.Contains("rowversion") || dbType.Contains("UniqueIdentifier") || dbType.Contains("VarBinary(MAX)")) { continue; } } //构造表达式的右边,值的一边 Expression right = Expression.Constant(p.GetValue(obj, null), p.PropertyType); //构造表达式的左边,property一端。 Expression left = Expression.Property(param, p.Name); //生成筛选表达式。即c.CustomerID == "Tom" Expression filter = Expression.Equal(left, right); if (condition == null) { condition = filter; } else { if (isAnd) condition = Expression.And(condition, filter); else condition = Expression.Or(condition, filter); } } } } } if (condition != null) { Expression<Func<TEntity, bool>> pred = Expression.Lambda<Func<TEntity, bool>>(condition, param); return source.Where(pred); } return source; }
  在这里,首先检查输入的参数是否为null。扩展方法其实是按静态方法执行的。它和静态方法唯一不同的就是系统自动为其加了一个Attribute,而这个Attribute只能通过在第一个参数加this关键字才能获得。而后,在影射类型上,修改后的函数只支持数值型和string型。其原因就是像 imager等并不支持条件查询。为了简化,我们只支持数值型和string型。这里最大的变化莫过于支持or条件了。调用Expression.And 或Expression.Or就可以了。还有一个变化就是ParameterExpression对象和xpression<Func< TEntity, bool>>被移出了foreach循环。这样,提高了效率,只是在最后才去生成条件。
  而实际上,大家大多使用是and条件,那再重载一个方法。
public static IQueryable<TEntity> Find<TEntity>(this IQueryable<TEntity> source, TEntity obj) where TEntity : class { return Find<TEntity>(source,obj,true);

延伸阅读

文章来源于领测软件测试网 https://www.ltesting.net/

TAG: CLR LINQ sql SQL Sql 进阶 Linq

21/212>

关于领测软件测试网 | 领测软件测试网合作伙伴 | 广告服务 | 投稿指南 | 联系我们 | 网站地图 | 友情链接
版权所有(C) 2003-2010 TestAge(领测软件测试网)|领测国际科技(北京)有限公司|软件测试工程师培训网 All Rights Reserved
北京市海淀区中关村南大街9号北京理工科技大厦1402室 京ICP备10010545号-5
技术支持和业务联系:info@testage.com.cn 电话:010-51297073

软件测试 | 领测国际ISTQBISTQB官网TMMiTMMi认证国际软件测试工程师认证领测软件测试网