EF6 - 没有做我对 .Any() 的预期

EF6 - not doing what I expected for .Any()

我被 EF 6 难住了....我有一个 Web 应用程序,它在性能方面表现非常糟糕。在分析时,我发现罪魁祸首之一是我的一种方法,该方法检查 EF6 实体上的集合是否为空。

基本上,我有:

public partial class BaseEntity
{
    public int BaseEntityId { get; set; }
    public string Name { get; set; }

    // a few more properties, of no concern here....

    // a lazily loaded collection of subitems        
    public virtual ICollection<Subitem> Subitems { get; set; }
}

public partial class Subitem
{
    public int SubitemId { get; set; }
    public int BaseEntityId { get; set; }
    public string Name { get; set; }

    // a few more properties, of no concern here....
}

在我的应用程序中,我需要检查 BaseEntity 的给定实例是否为 "empty" - 它被定义为没有子项。所以我将此方法 CheckIfEmpty 添加到第二个部分 class 文件中:

public partial class BaseEntity
{
    public bool IsEmpty 
    {
        return !Subitems.Any();
    }
}        

现在一个 BaseEntity 可以有成百上千个子项 - 所以我想用最有效的方法来检查是否有任何子项。我的 假设 是调用 .Any() 一个尚未从数据库加载的集合基本上会转化为

IF EXISTS(SELECT * FROM dbo.Subitems) ......

SQL 调用 - 或类似的东西 - 只是检查是否存在任何项目 - 或不存在。我特别选择 .Any() 而不是 .Count > 0 因为我知道检查计数需要枚举整个集合,因此当我只想知道是否(或不)任何项目存在时效率非常低。

不需要知道有多少存在,我对它们的细节也不感兴趣 - 只是一个简单的 YESNO is empty? 问题就足够了。

令我大吃一惊(和眼花缭乱)的是,EF6 将这个简单的 .Any() 调用变成了一个 SELECT 语句来加载 整个集合! - 这绝对是 不是 我讨价还价的......

那么有什么简单的方法可以简单地检查一个尚未加载的集合是否有任何值-或没有-WITHOUT从数据库加载完整的集合??

通过使用预加载方法和查询 DbSet,您会得到想要的:

context.Set<TEntity>().Any();

翻译成:

SELECT CASE WHEN EXISTS ( SELECT 1 FROM [TEntity] AS [m]) THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END