2011-12-01 65 views
1

我在Stack Exchange的Code Review(测试版)上发布了此代码段,以获取关于如何最好地重构多部分LINQ查询的一些反馈。如何将多部分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>(); 
     } 
    } 
+0

看来你的代码太复杂。它应该重新考虑。我赞同你。 –

+0

WTF是这个'where(0 == 1)'?您可以按照您构建过滤器的相同方式有条件地定义Except。如果SQL是性能问题,请检查管理工作室中执行的SQL查询和度量。 –

回答

2

我不明白为什么这样的:

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); 
+0

我想你最初发布的代码有同样的问题,对吧? – y0uri

+0

是的。在三元运算符周围有一个缺失的支架,再加上我刚刚返回IQueryable 并修复了它。再次感谢这一点。 – Nick