public static IQueryable<TSource> TestExtebsion<TSource>(this IQueryable<TSource> source) { Type _type = typeof(TSource); ParameterExpression parm = Expression.Parameter(_type, "p"); var body1 = Expression.Equal(Expression.Property(parm, _type.GetProperty("CompanyId")), Expression.Constant(1)); var body2 = Expression.Call(Expression.Property(parm, _type.GetProperty("CompanyName")) , typeof(string).GetMethod("Contains"), Expression.Constant("宁夏")); Expression bodys = Expression.Or(body1, body2); var expression = (Expression<Func<TSource, bool>>)Expression.Lambda<Func<TSource, bool>>(bodys, parm); return source.Where(expression); }
上面是自定义的一个扩展方法 目的是 后期自己构造一些 弱类型的查询条件 通过自己组装成为各种查询条件
var _query = Session.Query<Company>() .Select(p => new { p.CompanyId, p.CompanyName, p.CreateDate, p.Assets }) .TestExtebsion() .ToList();
这个是 NH 访问时调用上面的 扩展方法
问题来了
如果是
var expression = (Expression<Func<TSource, bool>>)Expression.Lambda<Func<TSource, bool>>(body1, parm);
单独用一个表达式 就没有任何问题
但是 如果像 第一个代码片段中那样 把 body1 和 body2 用 OR 或者 AND 拼接起来的话 (生成表达式如下)
p => ((p.CompanyId == 1) Or p.CompanyName.Contains("宁夏"))
就会报以下异常,反正就是不能 组合多个 表达式
无法将类型为“NHibernate.Hql.Ast.HqlBitwiseOr”的对象强制转换为类型“NHibernate.Hql.Ast.HqlBooleanExpression”。
求救
NH 是3.1
Expression bodys = Expression.Or(body1, body2);
注意Expression.Or 返回的是body1和body2的 bitwise or结果: body1 | body2, 如果想计算 body1 || body2,你应该使用Expression.OrElse
public static IQueryable<TSource> TestExtebsion<TSource>(this IQueryable<TSource> source) 换成 public static IQueryable<T> TestExtebsion<S>(this IQueryable<T> source)
<Func<TSource, bool>换成
<Func<TSource, S>
http://www.cnblogs.com/hun_dan/archive/2012/10/23/2735255.html
public static string RouteMap(Expression expression) { string sb = string.Empty; if (expression is BinaryExpression) { BinaryExpression be = ((BinaryExpression)expression); return Provider.BinaryProvider(be.Left, be.Right, be.NodeType); } else if (expression is MemberExpression) { MemberExpression me = ((MemberExpression)expression); return me.Member.Name; } else if (expression is NewArrayExpression) { NewArrayExpression ae = ((NewArrayExpression)expression); StringBuilder tmpstr = new StringBuilder(); foreach (Expression ex in ae.Expressions) { tmpstr.Append(RouteMap(ex)); tmpstr.Append(","); } return tmpstr.ToString(0, tmpstr.Length - 1); } else if (expression is MethodCallExpression) { MethodCallExpression mce = (MethodCallExpression)expression; if (mce.Method.Name == "Like") return string.Format("({0} like {1})", RouteMap(mce.Arguments[0]), RouteMap(mce.Arguments[1])); else if (mce.Method.Name == "NotLike") return string.Format("({0} Not like {1})", RouteMap(mce.Arguments[0]), RouteMap(mce.Arguments[1])); else if (mce.Method.Name == "In") return string.Format("{0} In ({1})", RouteMap(mce.Arguments[0]), RouteMap(mce.Arguments[1])); else if (mce.Method.Name == "NotIn") return string.Format("{0} Not In ({1})", RouteMap(mce.Arguments[0]), RouteMap(mce.Arguments[1])); } else if (expression is ConstantExpression) { ConstantExpression ce = ((ConstantExpression)expression); if (ce.Value == null) return "null"; else if (ce.Value is ValueType) return ce.Value.ToString(); else if (ce.Value is string || ce.Value is DateTime || ce.Value is char) return string.Format("'{0}'", ce.Value.ToString()); } else if (expression is UnaryExpression) { UnaryExpression ue = ((UnaryExpression)expression); return RouteMap(ue.Operand); } return string.Empty; }