使用ToList()避免DbSet对象计数

本文关键字:对象 DbSet 避免 ToList 使用 | 更新日期: 2023-09-27 18:25:34

使用C#实体框架v6.1.1,我试图在DbSet:上进行计数操作

//Items is a List<Item>
int count = db.MyObjects.Count(o => o.Items.FirstOrDefault(i => i.ItemID == 1) != default(Item));

我没有使用Contains,因为在使用Where Count等时存在已知的EF问题

现在,上面的行抛出一个NullReferenceException,告诉我对象引用没有设置为对象的实例。

更改为:

//Items is a List<Item>
int count = db.MyObjects.ToList().Count(o => o.Items.FirstOrDefault(i => i.ItemID == 1) != default(Item));

工作符合预期。

现在,我的假设是,DbSet作为一种代理,只有在请求时才延迟加载对象,而ToList()会强制它这样做

不过,我对这一切的表现感到担忧。有没有更好的方法来计算DbSet?我真的被迫到处打ToList()电话吗?

我注意到DbSet是而不是IEnumerable。

更新:我忘了提到我禁用了Lazy Loading,并且我在调用此代码时没有将Eagle Loading应用于Items集合,这可能解释了很多。

使用ToList()避免DbSet对象计数

你似乎有一个物化问题,但为了回答你的标题问题,我认为

int count = db.MyObjects
    .Where(x => x.Items.Any(y => y.ItemID == 1))
    .Count();

应该做

供调查:

Folders.Where(x => x.Files.Any(y => y.IdPseudoCountry == 16)).Count()
Folders.Count(x => x.Files.Any(y => y.IdPseudoCountry == 16))

导致:

SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    COUNT(1) AS [A1]
    FROM [dbo].[tableD] AS [Extent1]
    WHERE  EXISTS (SELECT 
        1 AS [C1]
        FROM [dbo].[tableF] AS [Extent2]
        WHERE ([Extent1].[idDossier] = [Extent2].[idDossier]) AND (16 = [Extent2].[idPays])
    )
)  AS [GroupBy1]

Folders.Count(x => x.Files.FirstOrDefault(y => y.IdPseudoCountry == 16) != default(File))

导致:

SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    COUNT(1) AS [A1]
    FROM ( SELECT 
        [Extent1].[idDossier] AS [idDossier], 
        (SELECT TOP (1) 
            [Extent2].[idFichier] AS [idFichier]
            FROM [dbo].[tableF] AS [Extent2]
            WHERE ([Extent1].[idDossier] = [Extent2].[idDossier]) AND (16 = [Extent2].[idPays])) AS [C1]
        FROM [dbo].[tableD] AS [Extent1]
    )  AS [Project2]
    WHERE [Project2].[C1] IS NOT NULL
)  AS [GroupBy1]

但就我而言,我也不例外。