查看实体的子表是不是包含任何记录的最快方法
Posted
技术标签:
【中文标题】查看实体的子表是不是包含任何记录的最快方法【英文标题】:Fastest way to see if a entity's child table contains any records查看实体的子表是否包含任何记录的最快方法 【发布时间】:2014-12-31 17:47:23 【问题描述】:阅读后:http://forums.devart.com/viewtopic.php?f=31&t=22425&p=74949&hilit=IQueryable#p74949
看来我应该使用IQueryable
来确定实体的子表是否有记录。
我最初的尝试是这样的: Ace.DirDs.Any();
这行代码(或类似的代码行)可能会运行数百次并导致巨大的性能问题。
所以通过阅读上面链接中的上一篇文章,我想我会尝试这样的事情:
IQueryable<DirD> dddd = CurrentContext.DirDs
.Where(d => d.AceConfigModelID == ace.ID).Take(1);
bool hasAChild = dddd.Any();
会有更好的方法吗?
【问题讨论】:
【参考方案1】:不需要Take(1)
。另外,这个打字更短。
bool hasAChild = CurrentContext.DirDs.Any(d => d.AceConfigModelID == ace.ID);
【讨论】:
我遇到了性能问题。上面的代码可以运行数百次。在我之前的代码中(在我发布的代码之前),我发现我正在创建一个 IEnumerable 并且可能会将数千条记录加载到内存中,然后查看是否存在一条记录。你的代码能防止这种情况发生吗? 您需要确保您使用的是 IQueryable 而不是 IEnumerable。 IEnumerable 将导致工作在内存中完成,而不是针对数据源。 我们需要看看CurrentContext.DirDs
是什么类型。
这个答案似乎是最快的方法。我最初的第一种方法是执行以下操作: entity.DirDs.Count() ,这需要 22-26 秒才能完成。而 CurrentContext.DirDs.Any(d => d.AceConfigModelID == ace.ID);需要 14-16 秒。我正在运行这些陈述数百次。它更好,但仍然比我想要的慢。【参考方案2】:
我可能错了,但我认为 Any()
仍然会导致从数据库服务器返回客户端的第一行的初始Read()
。你最好得到一个Count
,这样你只会得到一个号码:
bool hasAChild = CurrentContext.DirDs.Count(d => d.AceConfigModelID == ace.ID) > 0;
顺便说一句,这似乎不是在查看子表,只是DirDs
。
【讨论】:
抱歉,我最初的尝试是查看子表,这导致了巨大的性能问题。所以我试图使用 IQueryable 来避免这个问题。Count()
将导致服务器上的 I/O 比需要的多得多。 Any()
不会返回任何数据。【参考方案3】:
在您的示例中,您将 IQueryable 实现为 IEnumerable,因此执行了整个查询,然后您只需获取结果中的第一行。先前示例的答案中的任何一个都将比这成倍地快。使用 Count 时要小心,因为有属性 Count 和方法 Count()。为了避免您最初的问题(并且如果您选择 Count 路线),您将需要像在 Rhumborl 的示例中那样使用方法 Count() ,否则它将执行查询并为您提供 IEnumerable 的属性 Count被退回。 Count() 方法本质上转换为 SQL COUNT,而 Any() 方法转换为 SQL EXISTS(至少在使用 Microsoft SQL Server 时)。根据您的后端数据库是什么以及您使用的 EF 版本,在此级别上,一个可能比另一个更有效。
如果您遇到性能问题,我的投票是始终默认为 Any() 并探索 Count()。在数据库级别使用方法 Count() 仍然会产生性能成本,但这仍然取决于您使用的数据库。
这是一个很好的相关答案:Linq To Entities - Any VS First VS Exists
【讨论】:
以上是关于查看实体的子表是不是包含任何记录的最快方法的主要内容,如果未能解决你的问题,请参考以下文章