.NET 实体框架 - IEnumerable VS.可查询的 [英] .NET Entity Framework - IEnumerable VS. IQueryable

查看:21
本文介绍了.NET 实体框架 - IEnumerable VS.可查询的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请看这行代码.这是一个存储过程的调用,它返回一个ObjectResult<long?>.为了提取长值,我添加了 Select:

Please see this line of code. This is an invocation of a stored procedure, which returns an ObjectResult<long?>. In order to extract the long values I added the Select:

dbContext.FindCoursesWithKeywords(keywords).Select(l => l.Value);

基于智能感知,此 Select 返回 IEnumerable<long>.

Based on intellisense this Select returns IEnumerable<long>.

我不确定我是否在某处读过它,或者只是习惯了这个假设 - 我一直认为当 EF API 返回一个 IEnumerable (而不是 IQueryable) 那么这意味着结果已经实现.这意味着它们已从数据库中提取出来.

I'm not sure whether I read it somewhere or maybe just got used to this assumption - I always thought that when the EF API returns an IEnumerable (and not IQueryable) then this means that the results have been materialized. Meaning they've been pulled from the database.

我今天发现我错了(或者这可能是一个错误?).我一直收到错误

I found out today that I was wrong (or maybe that's a bug?). I kept getting the error

"新事务不允许,因为还有其他线程在会话中运行"

"New transaction is not allowed because there are other threads running in the session"

基本上,此错误告诉您,您正在尝试保存更改,而 db reader 仍在读取记录.

Basically, this error tells you that you're trying to save changes while the db reader is still reading records.

最终我解决了这个问题(我认为这是一个长镜头)并添加了 ToArray() 调用来实现 IEnumerable<long>...

Eventually I solved it by (what I considered a long shot) and added ToArray() call to materialize the IEnumerable<long>...

所以 - 底线 - 我应该期望 EF 的 IEnumerable 结果包含尚未实现的结果吗?如果是,那么有没有办法知道 IEnumerable 是否已实现?

So - the bottom line - should I expect IEnumerable results from EF to contain results that haven't materialized yet? If yes then is there a way to know whether an IEnumerable has been materialized or not?

感谢并道歉,如果这是那些duhhh"问题之一...... :)

Thanks and apologies if this is one of those 'duhhh' questions... :)

推荐答案

IQueryable 在您使用 Linq-to-entities = 您在应用程序中构建声明性 LINQ 查询时使用,该查询将被解释由 LINQ 提供程序作为 SQL 并在服务器上执行.一旦查询被执行(迭代),它将变成 IEnumerable 并且对象将根据迭代的需要被物化 = 不是立即的.

IQueryable is used when you are using Linq-to-entities = you are building declarative LINQ query in your application which will be interpreted by LINQ provider as SQL and executed on the server. Once the query is executed (iterated) it will turn to become IEnumerable and objects will be materialized as needed for iteration = not immediately.

一旦您调用存储过程,您就不会使用 Linq-to-entities,因为您的应用程序中没有内置声明式查询.查询/SQL 已经存在于数据库服务器上,您只是在调用它.这将返回 IEnumerable 但同样不会立即实现所有结果.结果将在迭代中实现.当您明确要求获取对象时,这是数据库游标/或 .NET 数据读取器的原理.

Once you call stored procedure you are not using Linq-to-entities because there is no declarative query built in your application. The query / SQL already exists on database server and you are just invoking it. This will return IEnumerable but again it will not materialize all results immediately. Results will be materialized as iterated. This is principle of database cursor / or .NET data reader when you explicitly ask for fetching object.

所以如果你这样称呼:

foreach (var keyword in dbContext.FindCoursesWithKeywords(keywords)
                                 .Select(l => l.Value))
{
    ...   
}

您正在一一获取课程(顺便说一句.如果您只对关键字感兴趣,为什么要加载整个课程?).在您完成或中断循环之前,您的数据阅读器会打开以获取记录.

You are fetching courses one by one (btw. why to load whole course if you are interested only in keywords?). Until you complete or break the loop your data reader is opened to fetch records.

如果你改为这样称呼:

foreach (var keyword in dbContext.FindCoursesWithKeywords(keywords)
                                 .ToList() // or ToArray 
                                 .Select(l => l.Value))
{
    ...
}

您将强制查询立即实现所有结果,并且循环将在内存中的集合而不是打开的数据库读取器上执行.

You will force query to materialize all results immediately and loop will perform on collection in memory instead of opened database reader.

IEnumerableIQueryable 之间的区别不在于获取数据的方式,因为 IQueryableIEnumerable.区别在于支持结构(必须实现这些接口).

Difference between IEnumerable and IQueryable is not in the way how data are fetched because IQueryable is IEnumerable. The difference is in backing construct (something must implement these interfaces).

这篇关于.NET 实体框架 - IEnumerable VS.可查询的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆