简体   繁体   English

获取 mongodb 文档但 Iqueriable 上的 ToListAsync 引发异常源 IQueryable 未实现 IAsyncEnumerable

[英]Getting mongodb documents but ToListAsync on Iqueriable throws exception The source IQueryable doesn't implement IAsyncEnumerable

I am using MongoDB.Driver 2.10.4我正在使用 MongoDB.Driver 2.10.4

I want to get all documents that have an id in a list of ids that I get from my controller我想从我的 controller 获得的 id 列表中获取所有具有 id 的文档

I am doing something like this我正在做这样的事情

            var pending_processes = mongo_context.collectionName
            .AsQueryable()
            .Where(x => request.ids.Contains(x.Id))
            .Select(x => new ViewModel()
            {
                process_id = x.Id,
                date = not important just accessing the x object
                state = new States()
                {
                    timeline = x.states.timeline,
                    part = x.states.part,
                }
            }).ToList();

The code above works fine but if I make my function async and do an await and replace ToList by ToListAsync I get the following error上面的代码工作正常,但如果我让我的 function 异步并执行等待并用 ToListAsync 替换 ToList,我会收到以下错误

The source IQueryable doesn't implement IAsyncEnumerable<Application.Process.Query.GetPendingProcesses.ViewModel>. Only sources that implement IAsyncEnumerable can be used for Entity Framework asynchronous operations.

Clearly there is something I am not getting here my concern is I don't want my code to run synchronously this would be really bad.很明显,我没有到达这里我担心的是我不希望我的代码同步运行,这真的很糟糕。 usually when dealing with postgresql context I always use the ToListAsync but here in order to use linq with mongo i had to use AsQueryable() and AsQueryable as I understand it does not get the data it's a normal query that I need to execute afterwards but when I use with it ToList everything works but when I use ToListAsync I get the error.通常在处理 postgresql 上下文时,我总是使用 ToListAsync 但在这里为了将 linq 与 mongo 一起使用,我必须使用 AsQueryable() 和 AsQueryable,因为据我所知它没有得到数据,这是一个正常的查询,我需要在之后执行但是当我使用它 ToList 一切正常,但是当我使用 ToListAsync 时出现错误。

I just want to know what is behind all of this and is the code above synchronous or asynchronous?我只想知道这一切的背后是什么,上面的代码是同步的还是异步的?

Sure you can keep it asynchronous, but first you have switch out AsQueryable to some other method which returns back and IQueryable .当然你可以让它保持异步,但首先你已经将AsQueryable切换到返回和IQueryable的其他方法。

In a nutshell ToListAsync() works on a IQueryable<T> only , when you turned it in to a IEnumerable via AsEnumerable() you lost the ability to call it.简而言之ToListAsync()适用于IQueryable<T> ,当您通过AsEnumerable()将其转换为IEnumerable时,您将失去调用它的能力。 Its explained well here在这里解释得很好

You have a couple of choices, either implement IDbAsyncEnumerable see here or change the result list you have into an async list with Task.FromResult()您有几个选择,要么实现 IDbAsyncEnumerable 参见此处,要么使用Task.FromResult()将您拥有的结果列表更改为async list

Option 1:选项1:

  // try this in your controller
  public async Task<List<PeopleStatesType>> GetAsyncStatesList()
  {
    //for e.g. 
    List<PeopleType> peopleList = new List<PeopleType>()
    {
      new PeopleType(){ Name = "Frank", Gender = "M" },
      new PeopleType(){ Name = "Rose", Gender = "F" }  //..      
    };

    var result = from e in peopleList
                 where e.Gender == "M"
                 select e;
    return await Task.FromResult(result.ToList());
  }

Option 2: Use this class选项 2:使用此class

public class AsyncEnumerableQuery<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T> {
    public AsyncEnumerableQuery(IEnumerable<T> enumerable) : base(enumerable) {
    }

    public AsyncEnumerableQuery(Expression expression) : base(expression) {
    }

    public IDbAsyncEnumerator<T> GetAsyncEnumerator() {
        return new InMemoryDbAsyncEnumerator<T>(((IEnumerable<T>) this).GetEnumerator());
    }

    IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator() {
        return GetAsyncEnumerator();
    }

    private class InMemoryDbAsyncEnumerator<T> : IDbAsyncEnumerator<T> {
        private readonly IEnumerator<T> _enumerator;

        public InMemoryDbAsyncEnumerator(IEnumerator<T> enumerator) {
            _enumerator = enumerator;
        }

        public void Dispose() {
        }

        public Task<bool> MoveNextAsync(CancellationToken cancellationToken) {
            return Task.FromResult(_enumerator.MoveNext());
        }

        public T Current => _enumerator.Current;

        object IDbAsyncEnumerator.Current => Current;
    }
}

// FindAll: with a condition like .Find(x => x.user == "Jone Doe") 
// see [here][3]
var task = collection.Find(p => true).ToListAsync();

Update Option 3 : Simple Async Get更新选项 3 :简单异步获取

public async Task<IEnumerable<MyMongoEntity>> Where(Expression<Func<MyMongoEntity, bool>> expression = null)
{
     return await context.GetCollection<MyMongoEntity>(typeof(MyMongoEntity).Name, expression).Result.ToListAsync();
}

Based on your comment, for a simple get documents collection, this helper should work.根据您的评论,对于一个简单的获取文档集合,这个助手应该可以工作。

From your error, it seems like the mongo_context.collectionName is returning something from Entity Framework?从您的错误来看,似乎mongo_context.collectionName从实体框架返回了一些东西?

Only sources that implement IAsyncEnumerable can be used for Entity Framework asynchronous operations.只有实现 IAsyncEnumerable 的源才能用于实体框架异步操作。

Make sure you are calling the AsQueryable extension method directly on the Mongo collection .确保直接在 Mongo 集合上调用AsQueryable扩展方法。 (Your code just shows mongo_context.collectionName.AsQueryable() so I'm not sure you're doing that) (您的代码仅显示mongo_context.collectionName.AsQueryable()所以我不确定您是否这样做)

Hooking into the LINQ provider requires getting access to an IQueryable instance.挂钩到 LINQ 提供程序需要访问IQueryable实例。 The driver provides an AsQueryable extension method on IMongoCollection .驱动程序在IMongoCollection上提供了AsQueryable扩展方法。

 var collection = db.GetCollection<Person>("people"); var queryable = collection.AsQueryable();

Reference: https://mongodb.github.io/mongo-csharp-driver/2.10/reference/driver/crud/linq/#queryable参考: https://mongodb.github.io/mongo-csharp-driver/2.10/reference/driver/crud/linq/#queryable

The AsQueryable extension above actually returns an IQueryable instance that implements IMongoQueryable and has all the same async extensions that other ORMs (Entity Framework, NHibernate, etc.) have - including ToListAsync .上面的AsQueryable扩展实际上返回了一个IQueryable实例,该实例实现IMongoQueryable并具有其他 ORM(实体框架、NHibernate 等)具有的所有相同的async扩展 - 包括ToListAsync

I just changed the way I query my context usind Find and and ForEachAsync and now all works well I just did not use AsQueryable because the mongodb driver as I understand it use these other functions but provides a way to use linq so I used the default methods without linq我只是更改了使用 Find 和 ForEachAsync 查询上下文的方式,现在一切正常我只是没有使用 AsQueryable,因为据我了解,mongodb 驱动程序使用这些其他功能,但提供了一种使用 linq 的方法,因此我使用了默认方法无 linq

            var result = new GetPendingProcessesViewModel();

        var filter = Builders<Domain.MongoDocuments.Process>.Filter
            .Where(x => own_processes.Contains(x.Id));

        await _elba_mongo_context.process.Find(filter)
            .ForEachAsync(x=>result.pending_processes_own.Add(
                new GetPendingProcessesViewModelItem()
                {
                    process_id = x.Id,
                    state = new States()
                    {
                        timeline = x.states.timeline,
                        part = x.states.part,
                        supplier = x.states.supplier
                    }}));

this is the link where you can get the documentation and references for your mongodb driver version https://mongodb.github.io/mongo-csharp-driver/这是您可以获得 mongodb 驱动程序版本https://mongodb.github.io/mongo-csharp-driver的文档和参考的链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ToArrayAsync() 抛出“源 IQueryable 未实现 IAsyncEnumerable” - ToArrayAsync() throws "The source IQueryable doesn't implement IAsyncEnumerable" .Net Core 单元测试错误 - 源 IQueryable 没有实现 IAsyncEnumerable&lt;…&gt; - .Net Core Unit Test Error - The source IQueryable doesn't implement IAsyncEnumerable<…> MSTest v2 和源 IQueryable 未使用 Entity Framework Core 实现 IAsyncEnumerable - MSTest v2 and The source IQueryable doesn't implement IAsyncEnumerable with Entity Framework Core 源 IQueryable 的提供者没有实现 IAsyncQueryProvider - The provider for the source IQueryable doesn't implement IAsyncQueryProvider 源 IQueryable 的提供程序未实现 IDbAsyncQueryProvider - The provider for the source IQueryable doesn't implement IDbAsyncQueryProvider 使用 MockQueryable 时,源“IQueryable”的提供程序未实现“IAsyncQueryProvider” - The provider for the source 'IQueryable' doesn't implement 'IAsyncQueryProvider' when using MockQueryable 尝试模拟时,源 IQueryable 未实现 IDbAsyncEnumerable - The source IQueryable doesn't implement IDbAsyncEnumerable when trying to mock .Net 5 Web Api - PagedList - 源“IQueryable”的提供者没有实现“IAsyncQueryProvider” - .Net 5 Web Api - PagedList - The provider for the source 'IQueryable' doesn't implement 'IAsyncQueryProvider' 在实体框架 6 SelectMany to Join 选项中查询抛出错误源 IQueryable 未实现 IDbAsyncEnumerable<MyModel> - In entity framework 6 SelectMany to Join option for query throwing error The source IQueryable doesn't implement IDbAsyncEnumerable<MyModel> ToListAsync抛出&#39;Value不能为null。&#39; 例外 - ToListAsync throws 'Value cannot be null.' Exception
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM