我正在编写一种方法,我希望能够根据订单中是否有一个或多个订购产品来过滤订单,这些产品存在于用户选择的产品中。目前我正在这样做:
SelectedProductIDs.Intersect(orderProductIDs).Any()
在每个订单上执行(数据库中总共约20,000个订单,并且预计会快速增长),其中SelectedProducts和orderProductIDs都是string []。我还试图为SelectedProductIDs和orderProductIDs使用预先生成的HashSets,但这在比较速度上没有明显差异。
然而,这两者都令人不快 - 每次选择更改约300毫秒 - 特别是假设UI中滑块可用的日期完全取决于此查询的结果,因此用户交互必须以某种方式停止。是否有(非常)明显更快的方法?
编辑:可能不够清楚 - 订单对象在启动时从SQL数据中实现,并且这些查询稍后在整个应用程序的辅助窗口中执行。 SQL与此问题的细节无关;这是一个LINQ-to-Objects问题。
答案 0 :(得分:4)
LINQ intersect将根据输入值重建新的HashSet
,无论您做什么,即使输入已经是HashSet
。它的实现在内部改变了哈希集(这就是它避免产生重复值的方式)所以重要的是要复制输入序列,即使它已经是HashSet
。
您可以创建自己的Intersect
方法来接受哈希集,而不是填充新的哈希集。尽管如此,为了避免变异,你必须选择基于行李的Intersect
而不是基于集合的Intersect
(即序列中的重复将全部产生)。显然,在你的情况下这不是问题:
public static IEnumerable<T> IntersectAll<T>(
this HashSet<T> set, IEnumerable<T> sequence)
{
foreach (var item in sequence)
if (set.Contains(item))
yield return item;
}
现在你可以写:
SelectedProductIDs.InsersectAll(orderProductIDs).Any();
每次都不需要重新构建hashset。
答案 1 :(得分:0)
听起来您正在将数据库中的所有值读入内存然后查询。如果您使用LINQ to EF,它会将LINQ查询转换为在数据库上运行的SQL查询,这可能会明显加快。