ORM(Linq-SQL EF)是不是从表中加载整个数据集?

Posted

技术标签:

【中文标题】ORM(Linq-SQL EF)是不是从表中加载整个数据集?【英文标题】:Does ORM (Linq-SQL EF) load entire data set from table?ORM(Linq-SQL EF)是否从表中加载整个数据集? 【发布时间】:2011-04-15 23:09:00 【问题描述】:

有关 ORM(Linq to SQL,EF 4)如何处理数据加载的问题。是否加载了整个数据集,如果是,我们可以阻止加载整个数据集并加载一个子集吗?例如,在实例化上下文和查询时,如果返回所有数据(数十万条记录)与实例化连接、为给定数据子集执行 proc 并查询该数据子集,似乎会出现巨大的性能问题。我没有看到很多线程解决了这个问题,提前谢谢!

【问题讨论】:

【参考方案1】:

不,它不会,因为 Linq to Sql/Eft 将解析查询以生成优化的 sql 查询来检索您的数据,据说滥用扩展方法(调用 GetEnumrator())或查询可能最终从表中加载所有项目。

滥用调用GetEnumerator()的扩展方法

context.Books.ToList().Where(somePredicate).Select(someSelector);

这将导致整个Books 表被加载,因为ToList() 将调用sql 查询来检索所有Book 对象。从那里你 WhereSelect 实际上是在 Linq to objects 而不是 Linq To Sql/Entities 上操作。

context.Books.Where(somePredicate).Select(someSelector).ToList();

只需将.ToList() 推到语句末尾,EF 就会将查询解析为有效的 sql 查询,并在调用.ToList() 时检索您的部分图书。

滥用Func<T, bool>

考虑以下,

Func<Book, bool> predicate = b=>b.Id == 3;
context.Where(predicate).ToList();

现在这看起来完全有效,但是一旦您运行查询,您会发现上下文正在加载所有Books,这是什么?简而言之,EF 无法将 Func&lt;T, bool&gt; 谓词解析为有效的 sql 语法,因为 Func&lt;&gt; 只是一个委托。这个简单的错误可能导致 EF 将所有 Books 加载到上下文中,然后针对加载的 Books 运行 Linq to Objects。

Expression<Func<Book, bool>> predicate = b=>b.Id == 3;
context.Where(predicate).ToList();

现在我们将使用Expression&lt;Func&lt;Book, bool&gt;&gt;,它只是一个表达式树,EF 知道如何解析表达式树,并且能够创建一个有效的 sql 语句,该语句只加载一个 Book,ID 为 3 .

我相信其他人能够加入更多可能导致加载整个表格的示例,但是这些是您最有可能遇到的。

【讨论】:

正是我想要的。谢谢【参考方案2】:

如果我理解您的问题,Linq 2 Sql 不会加载数据集中的所有内容。创建上下文并构建 linq 2 sql 语句后,只有语句中引用的表才会被拉回,除非您明确告诉 dataContext 使用 DataLoadOptions 加载相关表。

现在,如果您在谈论分页,请使用 Skip and Take。

其他人可以加入 EF,因为我没有太多经验,但我无法想象它会有太大的不同。不过我喜欢 Linq 2 sql,它对我来说已经足够快了。

【讨论】:

以上是关于ORM(Linq-SQL EF)是不是从表中加载整个数据集?的主要内容,如果未能解决你的问题,请参考以下文章

EF - 从表中获取数据给出空值

EF Code first主从表,删除更新从表

Dapper EF 等orm Mysql不支持事务解决办法

liquibase 从表中加载数据

如何在没有ORM的情况下使用SQLAlchemy查询从表中删除行?

.NET / LINQ-SQL / ASP.NET 中的连接字符串地狱