Dav*_*man 6 c# linq generics linq-to-entities code-generation
我正在使用T4为LINQ to Entities实体生成存储库.
存储库包含(除其他外)适合于分页的List方法.支持和不支持的方法的文档没有提到它,但是你不能Skip在无序上"调用" IQueryable.它会引发以下异常:
System.NotSupportedException:方法'Skip'仅支持LINQ to Entities中的排序输入.必须在方法'Skip'之前调用'OrderBy'方法.
我通过允许通过部分方法定义默认排序来解决它.但是我在检查表达式树是否确实包含一个问题时遇到了问题OrderBy.
我已将问题减少到尽可能少的代码:
public partial class Repository
{
partial void ProvideDefaultSorting(ref IQueryable<Category> currentQuery);
public IQueryable<Category> List(int startIndex, int count)
{
IQueryable<Category> query = List();
ProvideDefaultSorting(ref query);
if (!IsSorted(query))
{
query = query.OrderBy(c => c.CategoryID);
}
return query.Skip(startIndex).Take(count);
}
public IQueryable<Category> List(string sortExpression, int startIndex, int count)
{
return List(sortExpression).Skip(startIndex).Take(count);
}
public IQueryable<Category> List(string sortExpression)
{
return AddSortingToTheExpressionTree(List(), sortExpression);
}
public IQueryable<Category> List()
{
NorthwindEntities ent = new NorthwindEntities();
return ent.Categories;
}
private Boolean IsSorted(IQueryable<Category> query)
{
return query is IOrderedQueryable<Category>;
}
}
public partial class Repository
{
partial void ProvideDefaultSorting(ref IQueryable<Category> currentQuery)
{
currentQuery = currentQuery.Where(c => c.CategoryName.Contains(" ")); // no sorting..
}
}
Run Code Online (Sandbox Code Playgroud)
这不是我真正的实现!
但我的问题是,我该如何实现该IsSorted方法?问题是,LINQ到实体查询的是类型的始终ObjectQuery,它实现IOrderedQueryable.
那么我应该如何确保OrderBy表达式树中存在一个方法呢?是解析树的唯一选择吗?
更新
我添加了两个其他重载,以明确它不是关于如何向存储库添加排序支持,而是如何检查ProvideDefaultSorting部分方法是否确实添加OrderBy了表达式树.
问题是,第一个部分类是由模板生成的,而部分类的第二部分的实现是由团队成员在另一个时间完成的.您可以将它与.NET实体框架生成EntityContext的方式进行比较,它允许其他开发人员使用扩展点.因此,我想尝试使其健壮,并且在ProvideDefaultSorting未正确实现时不会崩溃.
所以问题可能更多,我如何确认ProvideDefaultSorting确实添加了对表达式树的排序.
更新2
新问题得到了回答,并被接受,我想我应该更改标题以更多地匹配问题.或者我应该保留当前的标题,因为它会引导人们遇到同样的问题吗?
您可以在 ProvideDefaultSorting 的返回类型中解决这个问题。此代码不构建:
public IOrderedQueryable<int> GetOrderedQueryable()
{
IQueryable<int> myInts = new List<int>() { 3, 4, 1, 2 }.AsQueryable<int>();
return myInts.Where(i => i == 2);
}
Run Code Online (Sandbox Code Playgroud)
这段代码可以构建,但很阴险,编码人员得到了他们应得的。
public IOrderedQueryable<int> GetOrderedQueryable()
{
IQueryable<int> myInts = new List<int>() { 3, 4, 1, 2 }.AsQueryable<int>();
return myInts.Where(i => i == 2) as IOrderedQueryable<int>;
}
Run Code Online (Sandbox Code Playgroud)
与 ref 相同的故事(这不会构建):
public void GetOrderedQueryable(ref IOrderedQueryable<int> query)
{
query = query.Where(i => i == 2);
}
Run Code Online (Sandbox Code Playgroud)