Welcome

首页 / 软件开发 / LINQ / Linq To Sql进阶系列(七)动态查询续及CLR与SQL在某些细节上的差别

Linq To Sql进阶系列(七)动态查询续及CLR与SQL在某些细节上的差别2011-08-20 博客园 Tom Song在上面一篇文章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;

}