LinqToNhibernate又叫我郁闷了:无法使用表达式参数

上文说到LinqToNhibernate的DateTime处理上存在一个陷阱。仔细想想的话,其实应该不仅仅是针对DateTime,而是LinqToNhibernate只能处理到hbm映射过的property这一个级别,再取property的property的时候就会有一些莫名其妙的问题。

这次来谈谈今天写代码的时候碰到的另一个问题:无法使用表达式参数。

先来看看我原来写的代码:

ExpandedBlockStart.gif 代码
         public  IQueryable < ChildEntity >  FindForIVOC(string bu, Guid centreId, string name, string idNo, IEnumerable < Guid >  programIds
            , Guid? serviceId, string className)
        {
            
return  Session.Linq < ChildEntity > (entityName)
                .
Where (child  =>
                       child.Centre.Id.Equals(centreId)
                       
&&  child.Name. Contains (name)
                       
&&  child.IdNo. Contains (idNo))
                .
Where (JoinProgram(programIds, now))
                .
Where (JoinService(serviceId, now))
                .
Where (JoinClass(className, now))
                .OrderBy(OrderByIdNo())
                .ThenBy(OrderById());
        }

 

为了以后方便的使用其中一部分的where子句,我理所当然的建立了JoinProgram、JoinService、JoinClass等等几个方法返回Expression<Func<ChildEntity, bool>>对象

之后我在得到的IQueryable<TEntity>对象上调用Count(),结果跑了异常:Expression argument must be of type ICollection. 

搜索了一下这个异常message,没有太多的结果,只是这里提了一下,说解决之道是把IQueryable换乘ICollection。。。囧。。。 

重新审视一下异常堆栈

ExpandedBlockStart.gif 代码
[InvalidOperationException: Expression argument must be of type ICollection.]
   NHibernate.Linq.Visitors.WhereArgumentsVisitor.GetCollectionContainsCriteria(Expression list, Expression containedExpr) 
+ 194
   NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitMethodCall(MethodCallExpression expr) 
+ 388
   NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp) 
+ 575
   NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) 
+ 274
   NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitAndAlsoExpression(BinaryExpression expr) 
+ 96
   NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitBinary(BinaryExpression expr) 
+ 52
   NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp) 
+ 194
   NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) 
+ 274
   NHibernate.Linq.Visitors.WhereArgumentsVisitor.GetExistsCriteria(MethodCallExpression expr) 
+ 493
   NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitMethodCall(MethodCallExpression expr) 
+ 1234
   NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp) 
+ 575
   NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) 
+ 274
   NHibernate.Linq.Visitors.ExpressionVisitor.VisitConditional(ConditionalExpression c) 
+ 62
   NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp) 
+ 319
   NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) 
+ 274
   NHibernate.Linq.Visitors.ExpressionVisitor.VisitLambda(LambdaExpression lambda) 
+ 21
   NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp) 
+ 639
   NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) 
+ 274
   NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitUnary(UnaryExpression expr) 
+ 34
   NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp) 
+ 140
   NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) 
+ 274
   NHibernate.Linq.Visitors.RootVisitor.HandleWhereCall(MethodCallExpression call) 
+ 92
   NHibernate.Linq.Visitors.RootVisitor.VisitMethodCall(MethodCallExpression expr) 
+ 907
   NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp) 
+ 575
   NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) 
+ 274
   NHibernate.Linq.Visitors.RootVisitor.VisitMethodCall(MethodCallExpression expr) 
+ 53
   NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp) 
+ 575
   NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) 
+ 274
   NHibernate.Linq.Visitors.NHibernateQueryTranslator.TranslateInternal(Expression expression) 
+ 81
   NHibernate.Linq.Visitors.NHibernateQueryTranslator.Translate(Expression expression, QueryOptions queryOptions) 
+ 43
   NHibernate.Linq.NHibernateQueryProvider.TranslateExpression(Expression expression) 
+ 575
   NHibernate.Linq.NHibernateQueryProvider.Execute(Expression expression) 
+ 17
   NHibernate.Linq.QueryProvider.System.Linq.IQueryProvider.Execute(Expression expression) 
+ 13
   System.Linq.Queryable.Count(IQueryable`
1  source)  + 310
   SNBusinessLogic.ServiceImpl.Pager.Page(IQueryable`
1  entities, Int32 startRow, Int32 maxResult)  in  D:\singapore\skoolnet\src\trunk\SkoolNet\SNBusinessLogic\ServiceImpl\Pager.cs: 12
   SNBusinessLogic.ServiceImpl.ChildServiceImpl.FindForIVOC(Guid centreId, String name, String idNo, IEnumerable`
1  programIds, Nullable` 1  serviceId, String className, Int32 startRow, Int32 maxResult)  in  D:\singapore\skoolnet\src\trunk\SkoolNet\SNBusinessLogic\ServiceImpl\ChildServiceImpl.cs: 49
   SNUserControls.Child.SearchChild.LoadSearchResults() 
in  D:\singapore\skoolnet\src\trunk\SkoolNet\SNUserControls\Child\SearchChild.ascx.cs: 101
   SNUserControls.Child.SearchChild.btnSearch_Click(Object sender, EventArgs e) 
in  D:\singapore\skoolnet\src\trunk\SkoolNet\SNUserControls\Child\SearchChild.ascx.cs: 71
   System.Web.UI.WebControls.ImageButton.OnClick(ImageClickEventArgs e) 
+ 98
   System.Web.UI.WebControls.ImageButton.RaisePostBackEvent(String eventArgument) 
+ 161
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) 
+ 29
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) 
+ 2981

 

发现异常是在处理where子句的地方抛出来的。为了定位错误,只留下一个参数为Func的where子句,OK了,在加上一个where子句就发生上面的错误。 

到网上找了找,虽然没有找到明确的说明,但是给出的例子里多个where语句确实是用表达式树把多个Expression合并成一个Expression传入where的。

以我的理解能力而言,大量使用表达式树实在是对代码的可读性造成很大的破坏,我还是老老实实的让我的各个方法返回Func<ChildEntity, bool>然后拼where语句的时候调用委托好了,比如说当我把代码改成这样,就可以顺利执行了

ExpandedBlockStart.gif 代码
         public  IQueryable < ChildEntity >  FindForIVOC( string  bu, Guid centreId,  string  name,  string  idNo, IEnumerable < Guid >  programIds
            , Guid
?  serviceId,  string  className)
        {
            var entityName 
=  bu  +  ChildEntity.StaticEntityClassName;
            var now 
=  DateTime.Now;
            
return  Session.Linq < ChildEntity > (entityName)
                .Where(child 
=>
                       child.Centre.Id.Equals(centreId)
                       
&&  child.Name.Contains(name)
                       
&&  child.IdNo.Contains(idNo)
                       
&&  JoinProgram(programIds, now).Invoke(child));
            
// .Where(JoinService(serviceId, now))
            
// .Where(JoinClass(className, now))
            
// .OrderBy(OrderByIdNo())
            
// .ThenBy(OrderById());
        }

 

总之LinqToNHibernate还是无法像LinqToSql那样非常方便随意的使用,不知道NH3.0内置的Linq Provider会怎么样呢?上个周末NH3.0的Alpha1已经发布了,期待正式版~~~ 

转载于:https://www.cnblogs.com/jiaxingseng/archive/2010/07/28/1787072.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值