Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF相关对象过滤器性能,can';你不能把它当作液体使用吗?_C#_Entity Framework_Iqueryable - Fatal编程技术网

C# EF相关对象过滤器性能,can';你不能把它当作液体使用吗?

C# EF相关对象过滤器性能,can';你不能把它当作液体使用吗?,c#,entity-framework,iqueryable,C#,Entity Framework,Iqueryable,我已经和EF合作了一段时间,虽然我觉得它很棒,但有一些东西让我难以忘怀 假设我在谈论经典的Order/OrderDetails关系。DbContext生成了所有内容。在其他属性中,我在类Order中有一个导航属性ICollection OrderDetails 现在,为什么没有干净的方法将导航属性用作IQueryable属性?这样,我就可以在SQL端运行WHERE,以获得良好的性能: var argDetails = order.OrderDetails.Where(d => d.Acti

我已经和EF合作了一段时间,虽然我觉得它很棒,但有一些东西让我难以忘怀

假设我在谈论经典的Order/OrderDetails关系。DbContext生成了所有内容。在其他属性中,我在类Order中有一个导航属性ICollection OrderDetails

现在,为什么没有干净的方法将导航属性用作IQueryable属性?这样,我就可以在SQL端运行WHERE,以获得良好的性能:

var argDetails = order.OrderDetails.Where(d => d.Active==true);
甚至

order.OrderDetails.Count();
相反,这会将所有相关细节提取到内存中,并使用EntityToObject进行筛选/计数

完全没有表现

有什么好的理由吗


谢谢

我希望我没有误解你的问题,但是你在找我吗

此外:


你说得对,关键是要拿到一张支票

例如:

Int32 i = ctx.Orders.Where(x => x.Id == 1).SelectMany(x => x.Details).Where(y => y.IsActive).Select(x => 1).Sum();
运行服务器端

因此,对你的问题的回答可能是:因为它可以用另一种方式来完成,而用这种方式可以完成如果用另一种方式无法完成的事情

请不要问我还有什么事:)

编辑

Int32 i = ctx.Orders.Where(x => x.Id == 1).SelectMany(x => x.Details).Where(y => y.IsActive).Count();
与几乎相同的查询等效:

SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        SUM(1) AS [A1]
        FROM [dbo].[OrderDetails] AS [Extent1]
        WHERE (1 = [Extent1].[Order_Id]) AND ([Extent1].[IsActive] = 1)
    )  AS [GroupBy1]

SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [dbo].[OrderDetails] AS [Extent1]
        WHERE (1 = [Extent1].[Order_Id]) AND ([Extent1].[IsActive] = 1)
    )  AS [GroupBy1]

IQueryable
是数据库查询的抽象,但是
IQueryable
提供的功能依赖于提供者,这使得它成为一个泄漏的抽象。许多人主张,
IQueryable
不应脱离数据层:

大多数开发人员都在努力使POCO不受依赖性的污染。外键和虚拟方法是大多数人都会容忍的折衷方案,但是
IQueryable
可能太过分了

您可以在此处投票支持以下内容:

参考资料:


这应该在SQL端运行where。一般来说,ORMs的主要缺点就是:针对DB的性能。由于这些原因,我还没有看到任何使用EF的大型项目。我无法回答您的问题,但如果您还没有阅读以下链接,您可能会想:@Martijn:这不在SQL端运行。通过seing返回类型:order.OrderDetails,您可以猜到它是一个HashSet集合。并且只有IQueryable可以延迟查询执行。@LittleSweetSeas:我想你是对的。。。我只是因为找不到一个有效的理由来解释为什么不在这里返回IQueryable而感到沮丧。我意识到有很多方法可以通过间接的方式“实现”我想要的东西,比如使用.Entry(…).Collection(…).Query()和其他许多。。。但我要问的是,为什么设计选择不保留“openforquery”导航属性,这是useOh ok的一个非常常见的情况。是的,我不知道。Dapper(这样使用的ORM)来自EF“一刀切”架构的性能问题。不需要选择1然后使用Sum,只需像OP那样使用
Count
。好的,这很有效。但要有效地使用导航属性,还需要一个棘手的解决方案。谢谢科林,这绝对有道理。我想根本解决方案是增强您共享的功能请求中处理的Include功能。同时,导航属性在性能批评场景中又会变得无用。。。这是一个微不足道的问题,没有多少人关注它。@Tuk如果您在上下文级别工作,有一些方法可以使用所需数据的子集填充导航属性。但我不能说我是那个想法的忠实粉丝。是的,我看过那个帖子。和@tschmit007的答案一样,这些都是有效的解决方法,但并不能解决导航属性问题
SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        SUM(1) AS [A1]
        FROM [dbo].[OrderDetails] AS [Extent1]
        WHERE (1 = [Extent1].[Order_Id]) AND ([Extent1].[IsActive] = 1)
    )  AS [GroupBy1]

SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [dbo].[OrderDetails] AS [Extent1]
        WHERE (1 = [Extent1].[Order_Id]) AND ([Extent1].[IsActive] = 1)
    )  AS [GroupBy1]