2010-03-11 100 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