简体   繁体   English

Linq(实体框架)与SQL进行动态数据分页

[英]Linq (Entity Framework) versus SQL for dynamic data paging

I have been looking at making the switch from SQL TableAdapters to Linq using Entity Framework, however some elements are stopping me whilst also driving me mad at the same time. 我一直在寻找使用Entity Framework从SQL TableAdapters切换到Linq,但是有些元素阻止了我,同时也让我发疯。

I have an ASP.NET 4.0 C# VS2010 Project site. 我有一个ASP.NET 4.0 C#VS2010项目站点。

My requirements are as follows: 我的要求如下:

  • Data must be pageable 数据必须是可分页的
  • Data must be orderable dynamically (ie ORDER BY SelectedColumnName ASC/DESC) 数据必须是动态可订购的(即ORDER BY SelectedColumnName ASC / DESC)
  • Data must be filterable based on web controls, text boxes, drop downs etc. Again, dynamically. 数据必须基于Web控件,文本框,下拉等可过滤。再次,动态。
  • Returned Columns must be dynamically constructable 返回的列必须是动态可构造的
  • Working with large tables must be as responsive as possible. 使用大型表必须尽可能地响应。 Paging helps with this. 分页有助于此。
  • On the frontend record information must be displayed. 在前端记录必须显示信息。 ie "Displaying Record 1-20 of 100" "Page 5 of 20" etc. 即“显示记录1-20 of 100”“第5页,共20页”等
    • Project is an internally accessible site only. Project仅是一个内部可访问的站点。 Not on the internet or anything. 不在互联网或任何东西。

Based on my requirements, I started to look at Dynamic Linq using the System.Linq.Dynamic namespace. 根据我的要求,我开始使用System.Linq.Dynamic命名空间查看Dynamic Linq。 I had some success but largely my queries became over-complicated. 我取得了一些成功,但很大程度上我的疑问变得过于复杂。

For my requirements, is there any real reason to use Linq and Entity Framework vs standard SQL? 根据我的要求,是否有任何真正的理由使用Linq和Entity Framework与标准SQL?

From what I can tell, standard SQL gives me all the control I need with a query language I can understand and control. 据我所知,标准SQL通过我能理解和控制的查询语言为我提供了所需的所有控件。 Linq is a language I am not amazingly familiar with, and doesn't allow me to make all the elements dynamic out of the box like I need to. Linq是一种我并不十分熟悉的语言,并且不允许我像我需要的那样使所有元素动态开箱即用。

Would I be wrong to go back to using SQL stored procs/table adapters for my querying? 回到使用SQL存储过程/表适配器进行查询时,我会错吗?

One thing I have learnt from my experimenting with Linq is that controlling the properties via the codebehind gives much better control of information, so I can use this data to parse stored procs for data to feed into gridviews. 我从Linq实验中学到的一件事是,通过代码隐藏控制属性可以更好地控制信息,因此我可以使用这些数据来解析存储过程,以便将数据输入到网格视图中。

This is an example of a Linq expression I was working with: 这是我正在使用的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();
    }
}

This is an example of the same thing via a SQL query: 这是通过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

I appreciate this is kind of an open question, if I could make it clearer I certainly would. 我很欣赏这是一个悬而未决的问题,如果我能让它更清楚我当然会。 However I am struggling to see the benefits of using Linq in my situation considering my requirements. 但是,考虑到我的要求,我很难看到在我的情况下使用Linq的好处。 Linq just doesn't seem very good at writing totally dynamic queries, and presumably has to execute SQL at the end anywhere (therefore SQL is faster?). Linq似乎并不擅长编写完全动态的查询,并且可能必须在任何地方执行SQL(因此SQL更快?)。

I've built front end controls that parse all I need into globalvars that I can then use to call the data: 我已经构建了前端控件,将我需要的所有内容解析为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";
    }

Using stored procedures will always be faster. 使用存储过程总是会更快。

Plus im sure you can see, that infact it is much easier to follow what is going on in your SQL code, rather than Linq. 另外,我确定你可以看到,事实上,更容易理解你的SQL代码,而不是Linq。

Actually do you mean calling that in an sql statement from your code. 实际上你的意思是在你的代码的sql语句中调用它。 Even then it is easier to read. 即使这样,它也更容易阅读。 And at the end of the day, they produce the same thing. 在一天结束时,他们生产同样的东西。

Linq is good for querying all ready obtained lists. Linq很适合查询所有准备好的列表。

For example, you have a list, but you now want objects that match WHERE x = y , and a new list WHERE x = z You can do this without requerying the Database. 例如,您有一个列表,但您现在需要与WHERE x = y匹配的对象,以及一个新列表WHERE x = z您可以在不重新查询数据库的情况下执行此操作。

If you are going to the Database, using sql query is fine. 如果你要去数据库,使用sql查询就可以了。 This can then be used by LINQ if necessary to manipulate the list further. 如果有必要,LINQ可以使用它来进一步操作列表。

Some people may disagree but its all down to prefence. 有些人可能不同意,但一切都归结为前戏。 I personally call them using SQL code statements. 我个人称他们使用SQL代码语句。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM