jus*_*uzz 23 ienumerable frameworks entity entity-framework iqueryable
请看这行代码.这是一个存储过程的调用,它返回一个ObjectResult<long?>.为了提取长值,我添加了Select:
dbContext.FindCoursesWithKeywords(keywords).Select(l => l.Value);
基于intellisense,这个Select返回IEnumerable<long>.
我不确定我是否在某处读过它或者只是习惯了这个假设 - 我一直认为当EF API返回IEnumerable(而不是IQueryable)时,这意味着结果已经实现.意味着他们已从数据库中撤出.
我今天发现我错了(或者这可能是个错误?).我一直收到错误
"不允许新事务,因为会话中还有其他线程在运行"
基本上,此错误告诉您在db阅读器仍在读取记录时尝试保存更改.
最终我通过(我认为是一个长镜头)解决了这个问题并增加ToArray()了实现IEnumerable<long>......
那么 - 底线 - 我应该期望IEnumerableEF的结果包含尚未实现的结果吗?如果是,那么有没有办法知道一个IEnumerable是否已实现?
如果这是'duhhh'问题之一,感谢并道歉...... :)
Lad*_*nka 29
IQueryable在使用Linq-to-entities时使用=您在应用程序中构建声明性LINQ查询,LINQ提供程序将其解释为SQL并在服务器上执行.一旦查询被执行(迭代),它将变为IEnumerable,并且对象将根据需要实现迭代=不立即.
一旦调用存储过程,就不会使用Linq-to-entities,因为应用程序中没有内置声明性查询.查询/ SQL已存在于数据库服务器上,您只是在调用它.这将返回IEnumerable但是它不会立即实现所有结果.结果将实现为迭代.当您明确要求获取对象时,这是数据库游标/或.NET数据读取器的原理.
所以如果你打这样的话:
foreach (var keyword in dbContext.FindCoursesWithKeywords(keywords)
                                 .Select(l => l.Value))
{
    ...   
}
您正在逐个学习课程(顺便说一句.如果您只对关键词感兴趣,为什么要加载整个课程?).在您完成或中断循环之前,您的数据阅读器将被打开以获取记录.
如果您改为这样称呼:
foreach (var keyword in dbContext.FindCoursesWithKeywords(keywords)
                                 .ToList() // or ToArray 
                                 .Select(l => l.Value))
{
    ...
}
您将强制查询立即实现所有结果,循环将在内存中执行而不是打开数据库读取器.
之间的差异IEnumerable和IQueryable不在数据是如何获取的,因为这样IQueryable的IEnumerable.不同之处在于支持构造(必须实现这些接口).
Cod*_*aos 11
处理一个IEnumerable<T>意味着所有进一步的操作将在C#代码中发生,即linq-to-objects.这并不意味着查询已经执行.
一旦降级为linq-to-objects,此时剩下的所有数据都需要从数据库中获取并发送到.net.这会降低性能急剧(例如数据库索引不会被LINQ到对象使用),但在另一方面LINQ到对象更灵活,因为它可以代替由什么限制执行任意的C#代码您的linq提供程序可以转换为SQL.
A IEnumerable<T>既可以是延迟查询,也可以是已实现的数据.标准linq运算符通常是延迟的,并且ToArray()/ ToList()始终具体化.
| 归档时间: | 
 | 
| 查看次数: | 18855 次 | 
| 最近记录: |