2010-03-11 46 views
1

我在使用LinqToSQL进行分页+动态排序时遇到了问题。这些是我的示例代码。LinqToSQL +分页+动态排序?

Using db As New MyDataContext(connectionString) 
     db.Log = new DebuggerWritter 
     Dim result = db.User.OrderBy(Function(u) u.UserId) 

     result = result.Skip((pageNo - 1) * pageSize).Take(pageSize)  
End Using 

这是由LINQToSQL生成的SQL脚本,它只检索特定行记录。

SELECT [t1].[UserId], [t1].[UserName] 
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY [t0].[UserId]) AS [ROW_NUMBER], [t0].[UserId], [t0].[UserName] 
    FROM [dbo].[User] AS [t0] 
    ) AS [t1] 
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1 
ORDER BY [t1].[ROW_NUMBER] 

但是,如果我执行的动态排序,

Using db As New MyDataContext(connectionString) 
     db.Log = new DebuggerWritter 
     Dim result = db.User 

     For Each s In sortExpressions 

      Dim expression As Func(Of User, Object) = Function(u) u.[GetType]().GetProperty(s.propertyName).GetValue(u, Nothing) 

      Select Case s.SortOrder 
       Case SortExpression.SortDirection.Ascending 
        result = result.OrderBy(expression).AsQueryable 
       Case SortExpression.SortDirection.Descending 
        result = result.OrderByDescending(expression).AsQueryable 
      End Select 
     Next 

     result = result.Skip((pageNo - 1) * pageSize).Take(pageSize) 
End Using 

这是此时产生的SQL脚本,

SELECT [t0].[UserId], [t0].[UserName] 
FROM [dbo].[User] AS [t0] 

怎么来寻呼控制脚本不产生和排序是走了?那我实现动态排序的方式是错误的吗?或者LinqToSQL不支持分页+动态排序? 帮助!!!

回答

1

你在你的代码中做什么不会工作。但是,我有点惊讶,LINQ to SQL不会抛出异常。

您调用result.OrderBy(expression)OrderBy方法是Enumerable.OrderBy方法,而不是Queryable.OrderBy方法。您已经注意到了这一点,因为它返回的对象是IEnumerable(Of User)而不是IQueryable(Of User)。出于这个原因,您可以通过致电AsQueryable()将其转换为IQueryable(Of User)。然而,调用AsQyeryable无法正常工作。原因是LINQ to SQL处理表达式树(基本上是IQueryable)。表达式树可以动态组合,就像您已经使用result = result.Skip一样。但是,它不适用于表达式树,而是使用编译方法调用的委托。尽管你可以将这样的编译方法调用转换为IQueryable,但LINQ to SQL无法对其进行分析,因为它仍然是编译代码(需要自检才能完成此操作,只有专用工具可用作Reflector支持)。在这种情况下,LINQ to SQL可能会忽略部分查询的完整顺序,因为它发现它无法处理的(编译的)方法调用。

所以,你当你这样做的解决方案只会工作如下:

Dim expression As Expression(Of Func(Of User, [ExpectedKeyHere]) = _ 
    ... creation of the expression here ... 

Select Case s.SortOrder 
    Case SortExpression.SortDirection.Ascending 
     result = result.OrderBy(expression) 
    Case SortExpression.SortDirection.Descending 
     result = result.OrderByDescending(expression) 
End Select 

然而有-yet-另一回事。你似乎循环了一组sortExpressions。虽然可以附加已经排序的集合,但必须使用result.ThenByresult.ThenByDescending调用已排序的集合。调用它与result.OrderBy将完全诉诸它;你将失去初始的排序顺序。要长话短说,也许你应该尝试构建某种EntitySorter对象,它允许你的方法的调用者指定排序顺序。您的服务方法可能不是这个样子(抱歉,这是C#):

public static Person[] GetAllPersons(IEntitySorter<Person> sorter) 
{ 
    Condition.Requires(sorter, "sorter").IsNotNull(); 

    using (var db = ContextFactory.CreateContext()) 
    { 
     IOrderedQueryable<Person> sortedList = 
      sorter.Sort(db.Persons); 

     return sortedList.ToArray(); 
    } 
} 

I've written a blog about exactly this,再次,这是C#,但我认为它会做的正是你所需要的。

祝你好运。

+0

谢谢,它真的为我工作。 – Kevin 2010-03-15 02:32:45