简体   繁体   English

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

[英]Avoiding DbSet objects count using ToList()

Using C# Entity Framework v6.1.1, I was trying to make a Count operation on a DbSet : 使用C#实体框架v6.1.1,我试图在DbSet上执行Count操作:

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

I did not use Contains, as there is a known EF issue on its use with Where Count etc. 我没有使用Contains,因为与Where Count等一起使用时存在一个已知的EF问题。

Now, the above line throws an NullReferenceException, telling me that object reference is not set to an instance of object. 现在,上面的代码行抛出NullReferenceException,告诉我对象引用未设置为对象的实例。

Changing it to: 更改为:

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

Works as expected. 可以正常工作。

Now, my assumption is that DbSet is working as a type of a proxy, loading lazily objects only when requested, something the ToList() forces it to. 现在,我的假设是DbSet充当代理的一种,仅在请求时才懒惰地加载对象,而ToList()强制它加载。

I am concerned though about the performance of all this. 我对这一切的表现感到担忧。 Is there a better way of making the count of a DbSet ? 有没有更好的方法来计数DbSet Am I really enforced to do the ToList() call everywhere? 我真的被迫在任何地方都执行ToList()调用吗?

I noticed that DbSet is not an IEnumerable . 我注意到DbSet 不是 IEnumerable

UPDATE: I forgot to mention that I have Lazy Loading disabled, and that I am invoking this code without having applied Eager Loading to the Items collection, which probably explains a lot. 更新:我忘了提到我禁用了“延迟加载”,并且我在没有将“快速加载”应用于Items集合的情况下调用了此代码,这可能解释了很多。

It seems you have a materialization problem but to answer your title question, I think that 看来您有一个实体化问题,但要回答您的标题问题,我认为

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

should do 应该做

For investigation: 调查:

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

leads to: 导致:

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]

when 什么时候

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

leads to: 导致:

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]

But in my case I have no exception in none case. 但就我而言,我也不例外。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM