在日期范围内从 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 查询来提高性能。