为了根据用户所选择的条件来动态构造linq查询,决定使用ExpressionTree来实现,因为在SIte表中的SiteNo是String类型的,所以界面上有个功能是用户填写SiteNo的范围,然后来查找,与是写如下语句
BinaryExpression siteNoExpression = Expression.AndAlso(
Expression.LessThanOrEqual(
Expression.Property(dimsite, propertyInfo),
Expression.Constant(txtStartSiteNo.Text, typeof(String))
),
Expression.GreaterThanOrEqual(
Expression.Property(dimsite, propertyInfo),
Expression.Constant(txtEndSiteNo.Text, typeof(String)))
);
与是杯具开始上演,发生异常如下:
没有为类型“System.String”和“System.String”定义二进制运算符 LessThanOrEqual。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 异常详细信息: System.InvalidOperationException: 没有为类型“System.String”和“System.String”定义二进制运算符 LessThanOrEqual。而在网上搜了下,原因是因为String并没有重载操作符>=和<=,所以大多都是使用CompareTo,但都没有使用Expression,而是直接使用查询表达式来实现的,如下:
var query = from item in context.Sites
where item.SiteNo.ComparentTo(txtStartNo.Text)>=0
那么Expression如何来写呢,众里寻它千百度的过程就省略了,直接贴结果:
ParameterExpression dimsite = Expression.Parameter(typeof(DimSite), "dimsite");
var propertyInfo = typeof(DimSite).GetProperty("SiteNo");
var methodInfo = typeof(String).GetMethod("CompareTo", new Type[] { typeof(String) });//因为CompareTo有重载,所以这里指定了下参数的类型,否则会报反射异常
BinaryExpression siteNoExpression =
Expression.GreaterThanOrEqual(
Expression.Call(
Expression.Property(dimsite, propertyInfo),
methodInfo,
Expression.Constant(txtStartSiteNo.Text, typeof(String))
),
Expression.Constant(0, typeof(Int32)) //比较String.CompareTo的返回结果和0,来实现>=的效果
);
var expressionTree = Expression.Lambda<Func<DimSite, Boolean>>(siteNoExpression, new ParameterExpression[] { dimsite });
IQueryable<DimSite> query = context.DimSites.Where(expressionTree);
AspNetPager1.RecordCount = query.Count();
最终的SQL语句如下:
SELECT COUNT(*) AS [value] FROM [Site] AS [t0] WHERE [t0].[SiteNo] >= @p0
不过用Expression来写,实在太复杂了,所以被网友踩了下,换成Lanbda表达式,如下:
Expression<Func<DimSite, Boolean>> siteNodeExpTree =
site =>
site.SiteNo.CompareTo(txtStartSiteNo.Text) >= 0 && site.SiteNo.CompareTo(txtEndSiteNo.Text) <= 0;
IQueryable<dimsite> query = context.DimSites.Where(siteNodeExpTree);AspNetPager1.RecordCount = query.Count();</dimsite>
这样简练多了.