MongoDB .Net Driver(C#驱动) Async 异步 “源IQueryable未实现IDbAsyncEnumerable错误”解决方案
一、错误详情
引起错误的代码如下。笔者是需要对一个Records的内嵌数组进行排序、分页操作。
// 页码
var index = 4;
// 页面大小
var size = 10;
// 转换为Queryable
var page = await _sensorNodes.AsQueryable()
// 查找对应的sensorNode
.Where(s => s.Id == _sensorNodeId)
// 选择Records内嵌数组
.SelectMany(s => s.Records)
// 根据记录时间排序
.OrderBy(r => r.RecorDateTime)
// 跳过 index - 1页数据
.Skip((index - 1) * size)
// 选取一页数据
.Take(size)
// 转换为集合
.ToListAsync();
发生了以下错误。
二、错误排查过程
1.遇到这个问题,笔者以为是驱动没有实现这些功能,但是查看了MongoDB .Net Driver源码,发现驱动已经有具体实现。如下图所示。
GitHub地址:
https://github.com/mongodb/mongo-csharp-driver/blob/master/src/MongoDB.Driver/Linq/MongoQueryable.cs
2.然后根据其命名空间,检查了using发现也已经引用了MongoDB.Driver.Linq命名空间。
3.经过排查,发现该ToListAsync()方法是由System.Linq实现的,不是由MongoDB.Driver.Linq实现,这就是问题根源所在。
4.解决方案。
1.如果在该类中没有使用到System.Linq中的方法,那么直接删除改引用即可。
2.如果使用了该方法,那么找到你需要使用的对应扩展静态类,就直接使用扩展静态类来调用扩展方法。如下代码所示。
将代码修改。
// 页码
var index = 4;
// 页面大小
var size = 10;
// 转换为Queryable
var filter = _sensorNodes.AsQueryable()
// 查找对应的sensorNode
.Where(s => s.Id == _sensorNodeId)
// 选择Records内嵌数组
.SelectMany(s => s.Records)
// 根据记录时间排序
.OrderBy(r => r.RecorDateTime)
// 跳过 index - 1页数据
.Skip((index - 1) * size)
// 选取一页数据
.Take(size);
// 使用Mongodb实现的扩展
var page = await IAsyncCursorSourceExtensions.ToListAsync(filter);
关键:var page = await IAsyncCursorSourceExtensions.ToListAsync(filter);