2012-03-11 87 views
1

我一直在尋找使用實體框架從SQL TableAdapters切換到Linq,但是有些元素阻止了我,同時也讓我發瘋。Linq(實體框架)與SQL的動態數據分頁

我有一個ASP.NET 4.0 C#VS2010項目網站。

我的要求如下:

  • 數據必須分頁
  • 數據必須訂購動態(即ORDER BY SelectedColumnName ASC/DESC)
  • 數據必須基於web控件是過濾,文本盒子,下降等。再次,動態。
  • 返回的列必須是可動態構建的
  • 使用大型表必須儘可能地做出響應。尋呼有助於此。
  • 必須顯示前端記錄信息。即「顯示記錄1-20 of 100」「第5頁,共20頁」等。
    • 項目僅限內部訪問站點。不在互聯網上或任何東西。

根據我的要求,我開始在動態的LINQ看使用System.Linq.Dynamic命名空間。我取得了一些成功,但主要是我的疑問變得過於複雜。

對於我的要求,是否有任何真正的理由使用Linq和實體框架與標準SQL?

從我所知道的情況來看,標準SQL爲我提供了所需的所有控件,並使用了我能理解和控制的查詢語言。 Linq是一種我不太熟悉的語言,並且不允許我像所需要的那樣使所有元素動態變化。

我會錯誤地回去使用SQL存儲過程/表適配器進行查詢嗎?

我從Linq的實驗中學到的一件事是,通過代碼隱藏控制屬性可以更好地控制信息,所以我可以使用這些數據來解析存儲的數據饋送到GridView的數據。

這是我正在同一個LINQ表達式的例子:

private void FetchData() 
{ 
    using (var Context = new ProjectEntities()) 
    { 
     string Fields = GetDynamicFields(); 

     var Query = 
      Context.Users 
      .Join(Context.UserStats,   // Table to Join 
       u => u.msExchMailboxGuid,  // Column to Join From 
       us => us.MailboxGuid,   // Column to Join To 
       (u, us) => new     // Declare Columns for the next Join 
       { 
        ObjectGuid = u.objectGuid, 
        msExchMailboxGuid = u.msExchMailboxGuid, 
        CompanyName = u.CompanyName, 
        ResellerOU = u.ResellerOU, 
        DisplayName = u.DisplayName, 
        MBXServer = u.MBXServer, 
        MBXSG = u.MBXSG, 
        MBXDB = u.MBXDB, 
        MBXWarningLimit = u.MBXWarningLimit, 
        MBXSendLimit = u.MBXSendLimit, 
        MBXSendReceiveLimit = u.MBXSendReceiveLimit, 
        extensionAttribute10 = u.extensionAttribute10, 
        legacyExchangeDN = u.legacyExchangeDN, 
        UserPrincipalName = u.UserPrincipalName, 
        Mail = u.Mail, 
        lastLogonTimeStamp = u.lastLogonTimestamp, 
        createTimeStamp = u.createTimeStamp, 
        modifyTimeStamp = u.modifyTimeStamp, 
        altRecipient = u.altRecipient, 
        altRecipientBL = u.altRecipientBL, 
        DeletedDate = u.DeletedDate, 
        MailboxGuid = us.MailboxGuid, 
        Date = us.Date, 
        AssociatedItemCount = us.AssociatedItemCount, 
        DeletedItemCount = us.DeletedItemCount, 
        ItemCount = us.ItemCount, 
        LastLoggedOnUserAccount = us.LastLoggedOnUserAccount, 
        LastLogonTime = us.LastLogonTime, 
        StorageLimitStatus = us.StorageLimitStatus, 
        TotalDeletedItemSize = us.TotalDeletedItemSize, 
        TotalItemSize = us.TotalItemSize, 
        MailboxDatabase = us.MailboxDatabase 
       }) 
      .Join(Context.TechContacts,   // Table to Join 
       u => u.UserPrincipalName,  // Column to Join From 
       tc => tc.UPN,     // Column to Join To 
       (u, tc) => new     // Declare Final Column Names 
       { 
        ObjectGuid = u.ObjectGuid, 
        msExchMailboxGuid = u.msExchMailboxGuid, 
        CompanyName = u.CompanyName, 
        ResellerOU = u.ResellerOU, 
        DisplayName = u.DisplayName, 
        MBXServer = u.MBXServer, 
        MBXSG = u.MBXSG, 
        MBXDB = u.MBXDB, 
        MBXWarningLimit = u.MBXWarningLimit, 
        MBXSendLimit = u.MBXSendLimit, 
        MBXSendReceiveLimit = u.MBXSendReceiveLimit, 
        extensionAttribute10 = u.extensionAttribute10, 
        legacyExchangeDN = u.legacyExchangeDN, 
        UserPrincipalName = u.UserPrincipalName, 
        Mail = u.Mail, 
        lastLogonTimeStamp = u.lastLogonTimeStamp, 
        createTimeStamp = u.createTimeStamp, 
        modifyTimeStamp = u.modifyTimeStamp, 
        altRecipient = u.altRecipient, 
        altRecipientBL = u.altRecipientBL, 
        DeletedDate = u.DeletedDate, 
        MailboxGuid = u.MailboxGuid, 
        Date = u.Date, 
        AssociatedItemCount = u.AssociatedItemCount, 
        DeletedItemCount = u.DeletedItemCount, 
        ItemCount = u.ItemCount, 
        LastLoggedOnUserAccount = u.LastLoggedOnUserAccount, 
        LastLogonTime = u.LastLogonTime, 
        StorageLimitStatus = u.StorageLimitStatus, 
        TotalDeletedItemSize = u.TotalDeletedItemSize, 
        TotalItemSize = u.TotalItemSize, 
        MailboxDatabase = u.MailboxDatabase, 
        // New Columns from this join 
        UPN = tc.UPN, 
        Customer_TechContact = tc.Customer_TechContact, 
        Customer_TechContactEmail = tc.Customer_TechContactEmail, 
        Reseller_TechContact = tc.Reseller_TechContact, 
        Reseller_TechContactEmail = tc.Reseller_TechContact, 
        Reseller_Name = tc.Reseller_Name 
       }) 
      .Where(u => true) 
      .OrderBy(GlobalVars.SortColumn + " " + GlobalVars.SortDirection) 
      .Select("New(" + Fields + ")"); 

     // Add Extra Filters 
     if (!(string.IsNullOrWhiteSpace(SearchCompanyNameTextBox.Text))) 
     { 
      Query = Query.Where("CompanyName.StartsWith(@0)", SearchCompanyNameTextBox.Text); 
     } 

     // Set the Record Count 
     GlobalVars.TotalRecords = Query.Count(); 

     // Add Paging 
     Query = Query 
      .Skip(GlobalVars.Skip) 
      .Take(GlobalVars.Take); 

     // GridView Datasource Binding 
     GridViewMailboxes.DataSource = Query; 
     GridViewMailboxes.DataBind(); 
    } 
} 

這是通過一個SQL查詢同樣的事情爲例:

DECLARE @SQLSTATEMENT NVARCHAR(4000); 
DECLARE @FieldList varchar(MAX); 
DECLARE @OrderBy varchar(100); 
DECLARE @OrderDirection varchar(100); 
DECLARE @PageSize int; 
DECLARE @StartRow int; 

SET @FieldList = 'u.UserPrincipalName, u.Mail, us.TotalItemsize, tc.UPN'; 
SET @OrderBy = 'u.CompanyName'; 
SET @OrderDirection = 'ASC'; 
SET @PageSize = 20; 
SET @StartRow = 80; 

SET @SQLSTATEMENT = ' 
SELECT TOP(@PageSize) * FROM 
(
SELECT ' + @FieldList + ' 
,row_number() OVER (ORDER BY @OrderBy ' + @OrderDirection + ') AS [row_number] 
FROM Users As u 
INNER JOIN UserStats as us 
ON u.msExchMailboxGuid = us.MailboxGuid 
INNER JOIN TechContacts AS tc 
ON tc.UPN = u.UserPrincipalName 
) AS r 
WHERE r.[row_number] > @StartRow ' 

EXEC sp_executesql @SQLSTATEMENT, 
N'@FieldList varchar(MAX), @OrderBy varchar(100), @OrderDirection varchar(100), @PageSize int, @StartRow int', 
@FieldList, @OrderBy, @OrderDirection, @PageSize, @StartRow 

我明白這是怎麼樣的一個懸而未決的問題,如果我能更清楚地說明,我當然會。然而,我在考慮我的要求的情況下努力看到使用Linq的好處。 Linq在編寫完全動態的查詢方面似乎不太好,並且大概必須在任何地方執行SQL(因此SQL更快?)。

我建立的一個解析所有我需要到globalvars,我就可以使用調用數據前端控制:

public class GlobalVars 
    { 
     public static int TotalRecords = 0; 
     public static int TotalPages = 0; 
     public static int CurrentPage = 0; 
     public static int LowerPage = 0; 
     public static int UpperPage = 0; 
     public static int Take = 0; 
     public static int Skip = 0; 
     public static string SortColumn = "CompanyName"; 
     public static string SortDirection = "Ascending"; 
    } 

回答

3

使用存儲過程總是會更快。

另外我確定你可以看到,事實上,跟隨你的SQL代碼而不是Linq會更容易。

其實你的意思是在你的代碼中的sql語句中調用它。 即使這樣也比較容易閱讀。而在一天結束時,他們會產生同樣的結果。

Linq適合查詢所有現成的列表。

例如,您有一個列表,但您現在想要的對象匹配WHERE x = y,並且有一個新列表WHERE x = z您可以在不重新查詢數據庫的情況下執行此操作。

如果你要去數據庫,使用sql查詢很好。如果需要的話,這可以被LINQ用來進一步處理列表。有些人可能會不同意,但它的一切都是爲了預防。我親自使用SQL代碼語句來調用它們。

+0

謝謝,就是我在找什麼。我可能會將我的SQL存儲過程存儲在表適配器中(這正是我現在所做的),但是從代碼隱藏中調用表適配器,然後將結果數據綁定到我的網格視圖中。這將使我最終控制關於發送給表適配器,同時保持頁面代碼相當乾淨:) – HungryHippos 2012-03-11 14:18:36