当前位置: 首页 > 编程语言 > C#

如何检查OrderBy是否存在于ObjectQuery表达式树中Share

时间:2023-04-10 12:22:47 C#

如何检查OrderBy是否存在于ObjectQuery表达式树中我正在使用T4为LINQtoEntities实体生成存储库。存储库包含(除其他外)适合分页的List方法。支持和不支持方法的文档没有提到它,但您不能“调用”跳过IQueryable。它抛出以下异常:System.NotSupportedException:方法“Skip”仅支持LINQtoEntities中的排序输入。“OrderBy”方法必须在“Skip”方法之前调用。我通过允许通过部分方法定义默认排序来解决它。但是我无法检查表达式树是否实际包含OrderBy。我已经将问题减少到尽可能少的代码:publicpartialclassRepository{partialvoidProvideDefaultSorting(refIQueryablecurrentQuery);publicIQueryableList(intstartIndex,intcount){IQueryablequery=List();ProvideDefaultSorting(参考查询);如果(!IsSorted(query)){query=query.OrderBy(c=>c.CategoryID);}returnquery.Skip(startIndex).Take(count);}publicIQueryableList(stringsortExpression,intstartIndex,intcount){returnList(sortExpression).Skip(startIndex).Take(count);}publicIQueryableList(stringsortExpression){returnAddSortingToTheExpressionTree(List(),sortExpression);}publicIQueryableList(){NorthwindEntitiesent=newNorthwindEntities();返回ent.Categories;}privateBooleanIsSorted(IQueryablequery){返回查询是IOrderedQueryable;}}publicpartialclassRepository{partialvoidProvideDefaultSorting(refIQueryablecurrentQuery){currentQuery=currentQuery.Where(c=>c.CategoryName.Contains(""));//不排序..}}这不是我真正的实现!但我的问题是,如何实现IsSorted方法?问题是LINQtoEntities查询始终是实现IOrderedQueryable的ObjectQuery类型那么我应该如何确保OrderBy方法存在于表达式树中?是解析树的唯一选择吗?更新我添加了两个重载以明确它不是关于如何向存储库添加排序支持,而是如何检查ProvideDefaultSorting部分方法是否确实已将OrderBy添加到表达式树。问题是第一个部分类是由模板生成的,而第二部分部分类的实现是由另一个团队成员在另一个时间完成的。您可以将此与.NETentity框架生成EntityContext的方式进行比较,后者允许其他开发人员使用扩展点。所以我想尝试使其健壮并且在ProvideDefaultSorting未正确实现时不会崩溃。所以问题可能更多,我如何确认ProvideDefaultSorting确实在表达式树中添加了排序。更新2新问题已得到回答和接受,我想我应该更改标题以更匹配问题。还是我应该保留当前的标题,因为它会导致人们遇到同样的问题?您可以在ProvideDefaultSorting的返回类型中修复此问题。此代码不构建:publicIOrderedQueryableGetOrderedQueryable(){IQueryablemyInts=newList(){3,4,1,2}.AsQueryable();返回myInts.Where(i=>i==2);这段代码是构造的,但是阴险的,编码人员得到了他们应得的。publicIOrderedQueryableGetOrderedQueryable(){IQueryablemyInts=newList(){3,4,1,2}.AsQueryable();将myInts.Where(i=>i==2)作为IOrderedQueryable返回;}与ref相同(这不会构建):publicvoidGetOrderedQueryable(refIOrderedQueryablequery){query=query.Where(i=>i==2);}分页依赖于强排序。为什么不紧耦合操作?这是一种方法:支持对象publicinterfaceIOrderByExpression{ApplyOrdering(refIQueryablequery);}publicclassOrderByExpression:IOrderByExpression{publicIQueryableApplyOrderBy(refIQueryablequery){query=query.OrderBy(exp);}//TODOOrderByDescending、ThenBy、ThenByDescending方法。私有表达式>exp=null;//TODO布尔降序?publicOrderByExpression(Expression>myExpression){exp=myExpression;}}有问题的方法:publicIQueryableList(intstartIndex,intcount,IOrderByExpressionordering){NorthwindEntitiesent=newNorthwindEntities();IQueryablequery=ent.Categories;if(ordering==null){ordering=newOrderByExpression(c=>c.CategoryID)}ordering.ApplyOrdering(refquery);返回query.Skip(startIndex).Take(count);一段时间后,调用方法:varquery=List(20,20,newOrderByExpression(c=>c.CategoryName));恐怕比这更难。您可以看到,在某些情况下,实体框架会默默地忽略OrderBy。所以仅仅在表达式树中寻找OrderBy是不够的。OrderBy必须在“正确”位置,“正确”位置的定义是实体框架的一个实现细节。您可能已经猜到了,我和您在同一个地方;我正在使用实体存储库模式并在表示层上执行Take/Skip。我使用的解决方案可能并不理想,但对于我正在做的事情来说已经足够好了,即直到最后一刻才进行任何排序,以确保OrderBy始终位于表达式树的最后。因此,任何将要接受/跳过(直接或间接)的东西都首先插入到OrderBy中。代码的结构使得这只能发生一次。感谢DavidB,我得到了以下解决方案。(对于部分方法未执行或仅返回其参数的情况,我必须添加检测)。publicpartialclassRepository{partialvoidProvideDefaultSorting(refIOrderedQueryablecurrentQuery);publicIQueryableList(intstartIndex,intcount){NorthwindEntitiesent=newNorthwindEntities();IOrderedQueryable查询=ent.;if(oldQuery.Equals(query))//部分方法对查询没有做任何事情,或者只是不存在{query=query.OrderBy(c=>c.CategoryID);}returnquery.Skip(startIndex).Take(count);}//剩下的。);//compiletimeforcedsotring}}它确保在编译时如果实现了分部方法,它至少应该保持IOrderdQueryable。而当partial方法没有实现或者只返回其参数时,query不会改变,会使用fallbacksort。ProvideDefaultSorting(参考查询);如果(!IsSorted(query)){query=query.OrderBy(c=>c.CategoryID);}更改为://应用默认排序query=query.OrderBy(c=>c.CategoryID);//添加到排序ProvideDefaultSorting(refquery);这不是一个完美的解决方案。它没有解决您所说的“在函数中订购过滤器”。它确实解决了“我忘记实施订购”或“我选择不订购”的问题。我在LinqToSql中测试了这个解决方案:publicvoidOrderManyTimes(){DataClasses1DataContextmyDC=newDataClasses1DataContext();varquery=myDC.Customers.OrderBy(c=>c.Field3);query=query.OrderBy(c=>c.Field2);query=query.OrderBy(c=>c.Field1);Console.WriteLine(myDC.GetCommand(query).CommandText);}生成(注意顺序的倒序):SELECTField1,Field2,Field3FROM[dbo].[Customers]AS[t0]ORDERBY[t0].[Field1],[t0].[Field2],[t0].[Field3]我已经实现了一个解决方案,可以通过主键Sort对任何集合进行配对,因为没有指定默认排序顺序。也许这对你有用。请参阅http://johnkaster.wordpress.com/2011/05/19/a-bug-fix-for-system-linq-dynamic-and-a-solution-for-the-entity-framework-4-skip-problem/用于讨论和通用代码。(以及随附的DynamicLINQ错误修复。)以上就是C#学习教程:如何检查ObjectQuery表达式树中是否存在OrderBy共享的所有内容。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: