C# 在搜索自定义对象并将其返回到新集合时需要提高性能

C# 在搜索自定义对象并将其返回到新集合时需要提高性能,c#,performance,linq,observablecollection,C#,Performance,Linq,Observablecollection,结果如下: Search Started: 9/20/2020 6:05:39 AM Search Completed: Took 00:00:00 Collection Created: Took -00:01:18.4322494 DataSource Created: Took 00:00:00 我要做的是在一个对象集合中搜索与搜索词匹配的任何对象。该集合用作winforms应用程序中datagridview的绑定数据源。在通过linq搜索集合之后,它将结果返回给ObservableCo

结果如下:

Search Started: 9/20/2020 6:05:39 AM
Search Completed: Took 00:00:00
Collection Created: Took -00:01:18.4322494
DataSource Created: Took 00:00:00
我要做的是在一个对象集合中搜索与搜索词匹配的任何对象。该集合用作winforms应用程序中datagridview的绑定数据源。在通过linq搜索集合之后,它将结果返回给ObservableCollection,然后将其设置为新的数据源。除了
SearchResults=newobservetecollection(SearchResultsQuery)之外,一切正常非常慢,正如您从我前面做的基准测试中所看到的

感谢您的帮助

产生这些结果的代码如下所示:

DateTime startTime = DateTime.Now;
Console.WriteLine($"Search Started: {startTime}");
SearchTerm = SearchTerm.ToUpper();

var SearchResultsQuery = from orderLine in new ObservableCollection<OrderLines.OrderLine>(OrderLineCollection)
                         where ( orderLine.BatchNumber != null && orderLine.BatchNumber.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.BatchStatus != null && orderLine.BatchStatus.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.CustomerItem != null && orderLine.CustomerItem.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.CustomerName != null && orderLine.CustomerName.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.CustomerPurchaseOrder != null && orderLine.CustomerPurchaseOrder.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.FGItem != null && orderLine.FGItem.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.IngItem != null && orderLine.IngItem.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.RawItem != null && orderLine.RawItem.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.ItemDescription != null && orderLine.ItemDescription.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.Machine != null && orderLine.Machine.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.NextPONumber != null && orderLine.NextPONumber.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.Note != null && orderLine.Note.Content.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.OrderNumber != null && orderLine.OrderNumber.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.Status_1 != null && orderLine.Status_1.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.Status_2 != null && orderLine.Status_2.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.Status_3 != null && orderLine.Status_3.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.Status_4 != null && orderLine.Status_4.ToString().ToUpper().Contains(SearchTerm) ) ||
                         ( orderLine.Status_Today != null && orderLine.Status_Today.ToString().ToUpper().Contains(SearchTerm) )
                         select orderLine;

TimeSpan searchTime = startTime - DateTime.Now;
startTime = DateTime.Now;
Console.WriteLine($"Search Completed: Took {searchTime}");

SearchResults = new ObservableCollection<OrderLine>(SearchResultsQuery); //THIS LINE IS SLOW

TimeSpan collectionTime = startTime - DateTime.Now;
startTime = DateTime.Now;
Console.WriteLine($"Collection Created: Took {collectionTime}");

bs.DataSource = SearchResults;

TimeSpan dataSourceTime = startTime - DateTime.Now;
Console.WriteLine($"DataSource Created: Took {dataSourceTime}");
DateTime startTime=DateTime.Now;
WriteLine($“搜索已开始:{startTime}”);
SearchTerm=SearchTerm.ToUpper();
var SearchResultsQuery=来自新ObservableCollection(OrderLineCollection)中的orderLine
其中(orderLine.BatchNumber!=null&&orderLine.BatchNumber.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.BatchStatus!=null&&orderLine.BatchStatus.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.CustomerItem!=null&&orderLine.CustomerItem.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.CustomerName!=null&&orderLine.CustomerName.ToString().ToUpper().Contains(搜索术语))||
(orderLine.CustomerPurchaseOrder!=null&&orderLine.CustomerPurchaseOrder.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.FGItem!=null&&orderLine.FGItem.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.IngItem!=null&&orderLine.IngItem.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.RawItem!=null&&orderLine.RawItem.ToString().ToUpper().Contains(搜索术语))||
(orderLine.itemsdescription!=null&&orderLine.itemsdescription.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.Machine!=null&&orderLine.Machine.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.nextponmber!=null&&orderLine.nextponmber.ToString().ToUpper().Contains(搜索术语))||
(orderLine.Note!=null&&orderLine.Note.Content.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.OrderNumber!=null&&orderLine.OrderNumber.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.Status_1!=null&&orderLine.Status_1.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.Status_2!=null&&orderLine.Status_2.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.Status_3!=null&&orderLine.Status_3.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.Status_4!=null&&orderLine.Status_4.ToString().ToUpper().Contains(SearchTerm))||
(orderLine.Status_Today!=null&&orderLine.Status_Today.ToString().ToUpper().Contains(SearchTerm))
选择订单行;
TimeSpan searchTime=startTime-DateTime.Now;
startTime=DateTime.Now;
WriteLine($“搜索完成:花费了{searchTime}”);
SearchResults=新的ObservableCollection(SearchResultsQuery)//这条线慢
TimeSpan collectionTime=startTime-DateTime.Now;
startTime=DateTime.Now;
WriteLine($“创建的集合:花费了{collectionTime}”);
bs.DataSource=搜索结果;
TimeSpan dataSourceTime=startTime-DateTime.Now;
WriteLine($“DataSource Created:take{dataSourceTime}”);

如何提高将LINQ结果引入新集合的性能?

需要考虑的一些事项:

切勿使用
DateTime
来衡量绩效。始终使用秒表或benchmark.net。永远不要测量算法的第一次运行,因为它将包括编译时间

另一个建议是使用能够提供逐行性能报告的more

新的ObservableCollection(SearchResultsQuery)//这条线慢

这很慢,因为这是运行查询的实际行。这没什么不正常的

新的ObservableCollection(OrderLineCollection)

您应该能够通过
OrderLineCollection
进行搜索。为什么要将所有内容复制到一个
可观察集合

如果许多属性是字符串,为什么要对它们运行
.ToString()

.ToUpper()
效率很低,因为它必须创建一个新字符串,不幸的是
。Contains
没有采用
StringComparison
参数的重载。有些人建议使用.IndexOf,但当我测试它时,它似乎比
.Contains

一种选择是将所有属性连接到一个大字符串,其缺点是结果可能不同,如果一个属性以“ab”结尾,而另一个属性以“cd”开头,则搜索“abcd”将为真。对于您的用例来说,这可能很重要,也可能无关紧要

另一种选择是将所有属性转换为字符串列表,作为预处理步骤,因此搜索只需检查列表中的所有项目。这似乎比连接属性要慢一点

以上两种方法都可以与
.aspallel()
结合使用,以便在多个线程上运行查询

第三种选择是使用专门为快速搜索而设计的东西

当我做类似的事情时,我得到大约700ms的原始代码,用于1000000个项目。使用字符串连接和AsParallel(不包括连接字符串)大约15毫秒。这应该足以实现交互式性能。如果你有更多的项目,你可能想找第三方这样做