如何组合多部分 LINQ to Entities 查询

发布于 2024-12-19 03:35:51 字数 7079 浏览 4 评论 0原文

我在 Stack Exchange 的代码审查(测试版)上发布了此代码片段,以获得有关如何最好地重构多部分的一些反馈< code>LINQ 查询。

由于对 LINQ 比较陌生,我不太确定从哪里开始这个查询。

如果有人能给我任何关于在方法中组合一些 LINQ 查询的建议,我将不胜感激;特别是主查询中的'排除' IQueryable 集合(请参阅评论)。

目前该查询的性能并不是特别好,如果您能提供任何建议以从代码角度提高其性能,我们将不胜感激。

在 Code Review 上收到的评论更具架构性,但是我目前无法将任何内容移动到数据库。

我很欣赏这是一个很大的方法,但我已经发布了全部内容来提供上下文。

预先感谢您提供的任何建议。

方法

    /// Get templates by username and company 
    public List<BrowsingSessionItemModel> GetItemBrowsingSessionItems( 
        int companyId, 
        string userName, 
        Boolean hidePendingDeletions, 
        Boolean hideWithAppointmentsPending, 
        Boolean hideWithCallBacksPending, 
        int viewMode, 
        string searchString, 
        List<int?> requiredStatuses, 
        List<int?> requiredSources, 
        string OrderBy, 
        BrowsingSessionLeadCustomField fieldFilter) 
    { 

        try 
        { 
            IQueryable<Lead> exclude1; 
            IQueryable<Lead> exclude2; 
            IQueryable<Lead> exclude3; 

            //To prepare call backs pending 
            if (hideWithCallBacksPending == true) 
            { 
                exclude1 = (from l1 in db.Leads 
                            where (l1.Company_ID == companyId) 
                            from l2 // Hiding Pending Call Backs 
                                 in db.Tasks 
                                 .Where(o => (o.IsCompleted ?? false == false) 
                                     && (o.TaskType_ID == (int)RecordEnums.TaskType.PhoneCall) 
                                     && (o.Type_ID == (int)RecordEnums.RecordType.Lead) 
                                     && (o.Item_ID == l1.Lead_ID) 
                                     && (o.Due_Date > EntityFunctions.AddDays(DateTime.Now, -1)) 
                                 ) 
                            select l1); 
            } 
            else 
            { 
                exclude1 = (from l1 in db.Leads 
                            where (0 == 1) 
                            select l1); 
            } 
            //To prepare appointments backs pending 
            if (hideWithAppointmentsPending == true) 
            { 
                exclude2 = (from a1 in db.Leads 
                            where (a1.Company_ID == companyId) 
                            from a2 // Hiding Pending Appointments 
                                 in db.Tasks 
                                 .Where(o => (o.IsCompleted ?? false == false) 
                                     && (o.TaskType_ID == (int)RecordEnums.TaskType.Appointment) 
                                     && (o.Type_ID == (int)RecordEnums.RecordType.Lead) 
                                     && (o.Item_ID == a1.Lead_ID) 
                                     && (o.Due_Date > EntityFunctions.AddDays(DateTime.Now, -1)) 
                                 ) 
                            select a1); 
            } 
            else 
            { 
                exclude2 = (from a1 in db.Leads 
                            where (0 == 1) 
                            select a1); 
            } 
            //To prepare deletions 
            if (hidePendingDeletions == true) 
            { 
                exclude3 = (from d1 in db.Leads 
                            where (d1.Company_ID == companyId) 
                            from d2 // Hiding Pending Deletions 
                                 in db.LeadDeletions 
                                 .Where(o => (o.LeadId == d1.Lead_ID)) 
                            select d1); 
            } 
            else 
            { 
                exclude3 = (from d1 in db.Leads 
                            where (0 == 1) 
                            select d1); 
            } 

            // MAIN QUERY <--
            IQueryable<Lead> list = (from t1 in db.Leads 
                        from t2 
                        in db.LeadSubOwners 
                        .Where(o => t1.Lead_ID == o.LeadId && o.Expiry >= DateTime.Now) 
                        .DefaultIfEmpty() 
                        where (t1.Company_ID == companyId) 
                        where ((t2.Username == userName) && (viewMode == 1)) || ((t1.Owner == userName) && (viewMode == 1)) || ((viewMode == 2)) // Either owned by the user or mode 2 (view all) 

                        select t1).Except(exclude1).Except(exclude2).Except(exclude3); 


            // Filter sources and statuses seperately 

            if (requiredStatuses.Count > 0) 
            { 
                list = (from t1 in list 
                        where (requiredStatuses.Contains(t1.LeadStatus_ID)) 
                        select t1); 
            } 
            if (requiredSources.Count > 0) 
            { 
                list = (from t1 in list 
                        where (requiredSources.Contains(t1.LeadSource_ID)) 
                        select t1); 
            } 



            // Do custom field filter here 
            if (fieldFilter != null) 
            { 
                string stringIntegerValue = Convert.ToString(fieldFilter.IntegerValue); 

                switch (fieldFilter.FieldTypeId) 
                { 

                    case 1: 
                        list = (from t1 in list 
                                from t2 
                                in db.CompanyLeadCustomFieldValues 
                                .Where(o => t1.Lead_ID == o.Lead_ID && fieldFilter.TextValue == o.LeadCustomFieldValue_Value) 
                                select t1); 
                        break; 
                    case 2: 
                        list = (from t1 in list 
                                from t2 
                                in db.CompanyLeadCustomFieldValues 
                                .Where(o => t1.Lead_ID == o.Lead_ID && stringIntegerValue == o.LeadCustomFieldValue_Value) 
                                select t1); 
                        break; 
                    default: 
                        break; 
                } 
            } 

            List<Lead> itemsSorted; // Sort here 

            if (!String.IsNullOrEmpty(OrderBy)) 
            { 
                itemsSorted = list.OrderBy(OrderBy).ToList(); 
            } 
            else 
            { 
                itemsSorted = list.ToList(); 
            } 


            var items = itemsSorted.Select((x, index) => new BrowsingSessionItemModel 
            { 
                Id = x.Lead_ID, 
                Index = index + 1 
            });  

            return items.ToList(); 
        } 
        catch (Exception ex) 
        { 

            logger.Info(ex.Message.ToString()); 
            return new List<BrowsingSessionItemModel>(); 
        } 
    } 

I posted this code snippet over at Stack Exchange's Code Review (beta) in order to obtain some feedback on how best to refactor a multi-part LINQ query.

Being relatively new to LINQ, I'm not really sure where to begin with this query.

If anybody could give me any advice on combining a few of the LINQ queries within the method, I'd appreciate it; especially the 'exclude' IQueryable collections into the main query (see comments).

The query is not particularly performant at the moment and any advice you could give in order to improve its performance from a code perspective would be appreciated.

The comments received on Code Review were more architectural, however I'm not currently in a position where I can move anything to the database at this time.

I appreciate it's a large method, but I've posted the whole lot to give context.

Thanks in advance for any advice you're able to give.

The Method

    /// Get templates by username and company 
    public List<BrowsingSessionItemModel> GetItemBrowsingSessionItems( 
        int companyId, 
        string userName, 
        Boolean hidePendingDeletions, 
        Boolean hideWithAppointmentsPending, 
        Boolean hideWithCallBacksPending, 
        int viewMode, 
        string searchString, 
        List<int?> requiredStatuses, 
        List<int?> requiredSources, 
        string OrderBy, 
        BrowsingSessionLeadCustomField fieldFilter) 
    { 

        try 
        { 
            IQueryable<Lead> exclude1; 
            IQueryable<Lead> exclude2; 
            IQueryable<Lead> exclude3; 

            //To prepare call backs pending 
            if (hideWithCallBacksPending == true) 
            { 
                exclude1 = (from l1 in db.Leads 
                            where (l1.Company_ID == companyId) 
                            from l2 // Hiding Pending Call Backs 
                                 in db.Tasks 
                                 .Where(o => (o.IsCompleted ?? false == false) 
                                     && (o.TaskType_ID == (int)RecordEnums.TaskType.PhoneCall) 
                                     && (o.Type_ID == (int)RecordEnums.RecordType.Lead) 
                                     && (o.Item_ID == l1.Lead_ID) 
                                     && (o.Due_Date > EntityFunctions.AddDays(DateTime.Now, -1)) 
                                 ) 
                            select l1); 
            } 
            else 
            { 
                exclude1 = (from l1 in db.Leads 
                            where (0 == 1) 
                            select l1); 
            } 
            //To prepare appointments backs pending 
            if (hideWithAppointmentsPending == true) 
            { 
                exclude2 = (from a1 in db.Leads 
                            where (a1.Company_ID == companyId) 
                            from a2 // Hiding Pending Appointments 
                                 in db.Tasks 
                                 .Where(o => (o.IsCompleted ?? false == false) 
                                     && (o.TaskType_ID == (int)RecordEnums.TaskType.Appointment) 
                                     && (o.Type_ID == (int)RecordEnums.RecordType.Lead) 
                                     && (o.Item_ID == a1.Lead_ID) 
                                     && (o.Due_Date > EntityFunctions.AddDays(DateTime.Now, -1)) 
                                 ) 
                            select a1); 
            } 
            else 
            { 
                exclude2 = (from a1 in db.Leads 
                            where (0 == 1) 
                            select a1); 
            } 
            //To prepare deletions 
            if (hidePendingDeletions == true) 
            { 
                exclude3 = (from d1 in db.Leads 
                            where (d1.Company_ID == companyId) 
                            from d2 // Hiding Pending Deletions 
                                 in db.LeadDeletions 
                                 .Where(o => (o.LeadId == d1.Lead_ID)) 
                            select d1); 
            } 
            else 
            { 
                exclude3 = (from d1 in db.Leads 
                            where (0 == 1) 
                            select d1); 
            } 

            // MAIN QUERY <--
            IQueryable<Lead> list = (from t1 in db.Leads 
                        from t2 
                        in db.LeadSubOwners 
                        .Where(o => t1.Lead_ID == o.LeadId && o.Expiry >= DateTime.Now) 
                        .DefaultIfEmpty() 
                        where (t1.Company_ID == companyId) 
                        where ((t2.Username == userName) && (viewMode == 1)) || ((t1.Owner == userName) && (viewMode == 1)) || ((viewMode == 2)) // Either owned by the user or mode 2 (view all) 

                        select t1).Except(exclude1).Except(exclude2).Except(exclude3); 


            // Filter sources and statuses seperately 

            if (requiredStatuses.Count > 0) 
            { 
                list = (from t1 in list 
                        where (requiredStatuses.Contains(t1.LeadStatus_ID)) 
                        select t1); 
            } 
            if (requiredSources.Count > 0) 
            { 
                list = (from t1 in list 
                        where (requiredSources.Contains(t1.LeadSource_ID)) 
                        select t1); 
            } 



            // Do custom field filter here 
            if (fieldFilter != null) 
            { 
                string stringIntegerValue = Convert.ToString(fieldFilter.IntegerValue); 

                switch (fieldFilter.FieldTypeId) 
                { 

                    case 1: 
                        list = (from t1 in list 
                                from t2 
                                in db.CompanyLeadCustomFieldValues 
                                .Where(o => t1.Lead_ID == o.Lead_ID && fieldFilter.TextValue == o.LeadCustomFieldValue_Value) 
                                select t1); 
                        break; 
                    case 2: 
                        list = (from t1 in list 
                                from t2 
                                in db.CompanyLeadCustomFieldValues 
                                .Where(o => t1.Lead_ID == o.Lead_ID && stringIntegerValue == o.LeadCustomFieldValue_Value) 
                                select t1); 
                        break; 
                    default: 
                        break; 
                } 
            } 

            List<Lead> itemsSorted; // Sort here 

            if (!String.IsNullOrEmpty(OrderBy)) 
            { 
                itemsSorted = list.OrderBy(OrderBy).ToList(); 
            } 
            else 
            { 
                itemsSorted = list.ToList(); 
            } 


            var items = itemsSorted.Select((x, index) => new BrowsingSessionItemModel 
            { 
                Id = x.Lead_ID, 
                Index = index + 1 
            });  

            return items.ToList(); 
        } 
        catch (Exception ex) 
        { 

            logger.Info(ex.Message.ToString()); 
            return new List<BrowsingSessionItemModel>(); 
        } 
    } 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

短叹 2024-12-26 03:35:51

我不明白为什么这样:

false == false

然后:

where (0 == 1)

然后对于排除 1 和 2:

            //To prepare call backs pending 
            var phoneCallTypeId = (int) RecordEnums.TaskType.PhoneCall;
            var exclude1 = GetExclude(hideWithCallBacksPending, companyId, phoneCallTypeId);

            //To prepare appointments backs pending       
            var appointmentTypeId = (int) RecordEnums.TaskType.Appointment;
            var exclude2 = GetExclude(hideWithCallBacksPending, companyId, appointmentTypeId);

使用以下 GetExclude 方法:

    private object GetExclude(bool hideWithCallBacksPending, int companyId, int typeId)
    {
        return hideWithCallBacksPending
                   ? (from l1 in db.Leads
                      where (l1.Company_ID == companyId)
                      from l2
                          // Hiding Pending Call Backs 
                          in
                          db.Tasks.Where(
                              o =>
                              (o.IsCompleted ?? false) &&
                              (o.TaskType_ID == typeId) &&
                              (o.Type_ID == (int) RecordEnums.RecordType.Lead) &&
                              (o.Item_ID == l1.Lead_ID) &&
                              (o.Due_Date > EntityFunctions.AddDays(DateTime.Now, -1)))
                      select l1)
                   : (from l1 in db.Leads where (0 == 1) select l1);
    }

Exclude3:

            //To prepare deletions    
            var exclude3 = hidePendingDeletions
                           ? (from d1 in db.Leads
                              where (d1.Company_ID == companyId)
                              from d2
                                  // Hiding Pending Deletions           
                                  in db.LeadDeletions.Where(o => (o.LeadId == d1.Lead_ID))
                              select d1)
                           : (from d1 in db.Leads where (0 == 1) select d1);

排除 1 和 2 可以被称为内联,因为它们很短:

// Either owned by the user or mode 2 (view all)      
...select t1)
    .Except(GetExclude(hideWithCallBacksPending, companyId, phoneCallTypeId))
    .Except(GetExclude(hideWithCallBacksPending, companyId, appointmentTypeId))
    .Except(exclude3);

I don't understand why this:

false == false

And that:

where (0 == 1)

Then for excludes 1 and 2:

            //To prepare call backs pending 
            var phoneCallTypeId = (int) RecordEnums.TaskType.PhoneCall;
            var exclude1 = GetExclude(hideWithCallBacksPending, companyId, phoneCallTypeId);

            //To prepare appointments backs pending       
            var appointmentTypeId = (int) RecordEnums.TaskType.Appointment;
            var exclude2 = GetExclude(hideWithCallBacksPending, companyId, appointmentTypeId);

using the following GetExclude method:

    private object GetExclude(bool hideWithCallBacksPending, int companyId, int typeId)
    {
        return hideWithCallBacksPending
                   ? (from l1 in db.Leads
                      where (l1.Company_ID == companyId)
                      from l2
                          // Hiding Pending Call Backs 
                          in
                          db.Tasks.Where(
                              o =>
                              (o.IsCompleted ?? false) &&
                              (o.TaskType_ID == typeId) &&
                              (o.Type_ID == (int) RecordEnums.RecordType.Lead) &&
                              (o.Item_ID == l1.Lead_ID) &&
                              (o.Due_Date > EntityFunctions.AddDays(DateTime.Now, -1)))
                      select l1)
                   : (from l1 in db.Leads where (0 == 1) select l1);
    }

Exclude3:

            //To prepare deletions    
            var exclude3 = hidePendingDeletions
                           ? (from d1 in db.Leads
                              where (d1.Company_ID == companyId)
                              from d2
                                  // Hiding Pending Deletions           
                                  in db.LeadDeletions.Where(o => (o.LeadId == d1.Lead_ID))
                              select d1)
                           : (from d1 in db.Leads where (0 == 1) select d1);

Excludes 1 and 2 can be called inline as they are short:

// Either owned by the user or mode 2 (view all)      
...select t1)
    .Except(GetExclude(hideWithCallBacksPending, companyId, phoneCallTypeId))
    .Except(GetExclude(hideWithCallBacksPending, companyId, appointmentTypeId))
    .Except(exclude3);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文