在日期范围内从 c# 列表中搜索对象 - 性能导向
Searching objects from c# list between date range - Performance Oriented
我正在使用下面的方法使用 LINQ 查询在日期范围内查找对象列表(来自共享点列表)。可以正常运行,但需要很多时间,可以优化吗?
public System.Collections.Generic.List<ItineraryModel> FilterDashboard(string StartDate, string EndDate ,ClientContext clientContext, SharePointContext spContext)
{
var src = this.SpHelper.getAllListData(clientContext).ToList<ItineraryModel>();
System.Collections.Generic.List<ItineraryModel> source2 = src.Where(delegate (ItineraryModel x)
{
if (!(System.Convert.ToDateTime(x.StartDate).Date > System.Convert.ToDateTime(EndDate).Date))
{
return !(System.Convert.ToDateTime(x.EndDate).Date < System.Convert.ToDateTime(StartDate).Date);
}
return false;
}).ToList<ItineraryModel>();
return source2.Distinct<ItineraryModel>().ToList<ItineraryModel>();
}
如果 src 有 1000 个元素,您将多少次将 StartDate 从字符串转换为 DateTime。如果你只做一次这样不是更有效率吗?
此外,您 return 一个列表。您确定所有来电者都需要完整列表吗?会不会是有些调用者只想知道有没有元素?也许他们只想要第一个元素,或者前 24 个元素显示在屏幕上。换句话说:return 一个 IEnumerable 而不是一个 List 会不会更有效率。
If you create a LINQ like function, always consider to return an IEnumerable instead of a List, especially if you don't need the List to create your function.
现在您忘了告诉我们 GetAllListData.But 的 return 值让我们假设 GetAllListData return 是 ItenaryModels 的 IEnumerable 序列。
显然每个 ItenaryModel 至少有一个 StartDate 和一个 EndDate。您不需要所有 ItenaryModels,您只想要那些在输入参数 startDate 和 endDate 的间隔内开始的 ItenaryModels,或者换句话说,其中 属性 StartDate >= 输入参数 startDate 和 属性 EndDate <=输入参数 endDate.
IEnumerable<ItenaryModel> FilterDashboard(string textStartDate, string textEndDate, ...)
{
// TODO: check for non-null textStartDate, textEndDate
// convert the input dates to DateTime:
DateTime startDate = DateTime.Parse(textStartDate);
DateTime endDate = Datetime.Parse(textEndDate);
// TODO: decide what to do if dates can't be parsed
// TODO: decide what to do if startDate > endDate?
IEnumerable<ItenaryModel> itenaryModels = this.SpHelper.getAllListData(clientContext);
// the easiest is a foreach, alternatively use a LINQ where.
foreach (var itenaryModel in itenaryModels)
{
DateTime itenaryStartDate = DateTime.Parse(itenaryModel.StartDate.Date);
DateTime itenaryEndDate = DateTime.Parse(itenaryMode.EndDate.Date);
// TODO: decide what to do if can't be parsed
if (startDate <= itenaryStartDate && itenaryEndDate <= endDate)
{
// put this itenaryModel in the returned enumeration
yield return itenaryModel;
}
}
}
或者,您可以在其中使用 LINQ。这不是更快!
DateTime startDate = DateTime.Parse(textStartDate);
DateTime endDate = Datetime.Parse(textEndDate);
IEnumerable<ItenaryModel> itenaryModels = this.SpHelper.getAllListData(clientContext);
return itenaryModels.Where(itenaryModel =>
startDate <= DateTime.Parse(itenaryModel.StartDate.Date) &&
DateTime.Parse(itenaryModel.EndDate.Date) <= endDate);
您是将列表项作为一个整体加载到内存中,然后进行搜索。 @Harald Coppoolse 给出了有关 LINQ 的所有可能答案。
作为替代方法,您可以为此使用 CAML 查询。您正在使用 SPHelper
,其内部结构对我来说是陌生的。但是您可以使用旧式 SharePoint CAML 查询来提高性能。
我正在使用下面的方法使用 LINQ 查询在日期范围内查找对象列表(来自共享点列表)。可以正常运行,但需要很多时间,可以优化吗?
public System.Collections.Generic.List<ItineraryModel> FilterDashboard(string StartDate, string EndDate ,ClientContext clientContext, SharePointContext spContext)
{
var src = this.SpHelper.getAllListData(clientContext).ToList<ItineraryModel>();
System.Collections.Generic.List<ItineraryModel> source2 = src.Where(delegate (ItineraryModel x)
{
if (!(System.Convert.ToDateTime(x.StartDate).Date > System.Convert.ToDateTime(EndDate).Date))
{
return !(System.Convert.ToDateTime(x.EndDate).Date < System.Convert.ToDateTime(StartDate).Date);
}
return false;
}).ToList<ItineraryModel>();
return source2.Distinct<ItineraryModel>().ToList<ItineraryModel>();
}
如果 src 有 1000 个元素,您将多少次将 StartDate 从字符串转换为 DateTime。如果你只做一次这样不是更有效率吗?
此外,您 return 一个列表。您确定所有来电者都需要完整列表吗?会不会是有些调用者只想知道有没有元素?也许他们只想要第一个元素,或者前 24 个元素显示在屏幕上。换句话说:return 一个 IEnumerable 而不是一个 List 会不会更有效率。
If you create a LINQ like function, always consider to return an IEnumerable instead of a List, especially if you don't need the List to create your function.
现在您忘了告诉我们 GetAllListData.But 的 return 值让我们假设 GetAllListData return 是 ItenaryModels 的 IEnumerable 序列。
显然每个 ItenaryModel 至少有一个 StartDate 和一个 EndDate。您不需要所有 ItenaryModels,您只想要那些在输入参数 startDate 和 endDate 的间隔内开始的 ItenaryModels,或者换句话说,其中 属性 StartDate >= 输入参数 startDate 和 属性 EndDate <=输入参数 endDate.
IEnumerable<ItenaryModel> FilterDashboard(string textStartDate, string textEndDate, ...)
{
// TODO: check for non-null textStartDate, textEndDate
// convert the input dates to DateTime:
DateTime startDate = DateTime.Parse(textStartDate);
DateTime endDate = Datetime.Parse(textEndDate);
// TODO: decide what to do if dates can't be parsed
// TODO: decide what to do if startDate > endDate?
IEnumerable<ItenaryModel> itenaryModels = this.SpHelper.getAllListData(clientContext);
// the easiest is a foreach, alternatively use a LINQ where.
foreach (var itenaryModel in itenaryModels)
{
DateTime itenaryStartDate = DateTime.Parse(itenaryModel.StartDate.Date);
DateTime itenaryEndDate = DateTime.Parse(itenaryMode.EndDate.Date);
// TODO: decide what to do if can't be parsed
if (startDate <= itenaryStartDate && itenaryEndDate <= endDate)
{
// put this itenaryModel in the returned enumeration
yield return itenaryModel;
}
}
}
或者,您可以在其中使用 LINQ。这不是更快!
DateTime startDate = DateTime.Parse(textStartDate);
DateTime endDate = Datetime.Parse(textEndDate);
IEnumerable<ItenaryModel> itenaryModels = this.SpHelper.getAllListData(clientContext);
return itenaryModels.Where(itenaryModel =>
startDate <= DateTime.Parse(itenaryModel.StartDate.Date) &&
DateTime.Parse(itenaryModel.EndDate.Date) <= endDate);
您是将列表项作为一个整体加载到内存中,然后进行搜索。 @Harald Coppoolse 给出了有关 LINQ 的所有可能答案。
作为替代方法,您可以为此使用 CAML 查询。您正在使用 SPHelper
,其内部结构对我来说是陌生的。但是您可以使用旧式 SharePoint CAML 查询来提高性能。