实体框架应用位置过滤器时是否选择内存中的所有行?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了实体框架应用位置过滤器时是否选择内存中的所有行?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2403字,纯文字阅读大概需要4分钟。
内容图文
有一件事情让我感到困惑.我认为EF选择表中的所有行(所有记录).
让我给你看一个例子.
public Category GetByID(int Id)
{
return context.Categories.Find(Id);
}
表中有很多记录,当我用断点检查它们时,我不仅可以看到编号为I的所有记录,还可以看到所有记录.如果表中有1万条记录怎么办?我测试一下.我将所有记录手动复制到数据库中,并制作了3万条记录.
这样的表达
IEnumerable<Category> categories = categoryRepository
.Where(x => x.Published == true)
.ToList();
我看到有断点的3万条记录.但是表中至少有1万个发布错误.
实体框架是否首先将所有记录提取到内存中,然后过滤它们?
解决方法:
TL; DR
您的categoryRepository很可能破坏了EF的IQueryable<>表达式树,并实现整个Category表,以便运行.Where谓词.请参阅下面的示例.
更多详情
简短的回答是“否”,条件是实体框架能够解析IQueryable< I>.表达式(包括.Where谓词),它将使用您要定位的RDBMS的适当查询提供程序将关联的表达式树转换为本地Sql,从而实现Sql的所有优势,例如使用索引.
根据我的评论,EF不会这样做的常见原因之一是,如果IQueryable机制已被篡改,例如,如果您的存储库模式实现使用了IEnumerable< T> ;, overload of the Where predicate ,而不是IQueryable overload.
结果,EF除了提取表并针对谓词函数执行每一行,以确定该行是否与您的谓词匹配之外,别无选择.
顺便说一句,在存储库和/或工作单元包装器中包装DbContext是否有价值,这是一个debate,因为DbContext是事务性的,可以执行缓存,可以在单元测试期间进行模拟,并且现在支持多种数据库.
实例化发生的位置及其如何影响性能的示例
(实际上执行Sql查询的时间通常称为实现)
我已经排除了OP的存储库-即我们直接使用了DbContext.
最好:
var miniFoos = myDbContext.MyFooSet
.Where(f => f.SomeProperty = "foo")
.Select(f => new {...})
.ToList();
这很好,因为在将数据具体化为List(匿名类型)之前,我们仅对SQL中需要的列应用了谓词和投影.
好:
var foos = myDbContext.MyFooSet
.Where(f => f.SomeProperty = "foo")
.ToList() // Or .AsEnumerable(), or other materialization methods
.Select(f => new {...}); // Subset of fields
这不是理想的,因为尽管在实现之前应用了.Where子句,但我们将返回Foo表中的完整列,只是为了丢弃不必要的列.这意味着不必要的I / O,而且Sql可能只能够使用索引来执行查询.
不好-永远不要这样做
var foos = myDbContext.MyFooSet
.AsEnumerable() // (or `ToList()`, same problem)
.Where(f => f.SomeProperty = "foo")
.Select(f => new {...}); // Subset of fields
这似乎是OP所经历的-因为表在任何之前都已实现.在进行过滤的地方,整个表都被检索到内存中,而过滤则是使用Linq to Objects进行的.
在不使用表达式或不使用IEnumerable< T>的谓词构建器应用自定义时,也会发生此问题.而不是IQueryable< T> -IEnumerable没有关联的表达式树,因此无法解析为Sql.
内容总结
以上是互联网集市为您收集整理的实体框架应用位置过滤器时是否选择内存中的所有行?全部内容,希望文章能够帮你解决实体框架应用位置过滤器时是否选择内存中的所有行?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。