我在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>();
}
}
看来你的代码太复杂。它应该重新考虑。我赞同你。 –
WTF是这个'where(0 == 1)'?您可以按照您构建过滤器的相同方式有条件地定义Except。如果SQL是性能问题,请检查管理工作室中执行的SQL查询和度量。 –