Alexander Myltsev
Alexander Myltsev

Reputation: 499

IQueryable doesn't implement IDbAsyncEnumerable

The question was originally asked at http://entityframework.codeplex.com/discussions/399499#post928179 .

Good day! Please tell me if it is wrong place to post this question.

I have a query as follows:

IQueryable<Card> cardsQuery =
  dataContext.Cards
  .Where(predicate)
  .OrderByDescending(kc => kc.SendDate)
  .AsQueryable();

Then I try:

Task<Card[]> result = cardsQuery.ToArrayAsync();

And then exception rises:

The source IQueryable doesn't implement IDbAsyncEnumerable<Models.Card>

I use modified version of 'EF 5.x DbCotext generator'.

How to avoid it?

UPDATE

Important remark is that I have method to produce IQuerayble<Card> as follows:

class Repository {
  public IQueryable<Card> GetKudosCards(Func<Card, bool> predicate) {
    IEnumerable<KudosCard> kudosCards = kudosCardsQuery.Where(predicate);
     return kudosCards
            .OrderByDescending(kc => kc.SendDate)
            .AsQueryable();
  }
}

Upvotes: 8

Views: 18912

Answers (6)

aru
aru

Reputation: 778

I just replaced

using System.Data.Entity;

with

using Microsoft.EntityFrameworkCore;

Solved issue.

Upvotes: 0

aj go
aj go

Reputation: 714

If you want to use the List<T> for Linq query, Avoid chaining it with ToListAsync(). It uses the class IDbAsyncEnumerable that is not available to a normal List<T> object

Upvotes: 0

Yaschalew Erkihun
Yaschalew Erkihun

Reputation: 135

I had the same problem when I was using the LinqKit library expression builder, which in the end, was producing AsQueryable(), and very surprisingly it was happening for me from the XUnit Integration Tests call.

I was going wild about why the same problem wasn't happening when calling the same API endpoint via Swagger.

It turned out I had to do an elementary change. I had to replace:

using System.Data.Entity;

with:

using Microsoft.EntityFrameworkCore;   

Upvotes: 12

Arsen Khachaturyan
Arsen Khachaturyan

Reputation: 8340

I had the same problem when I was using the LinqKit library expression builder, which in the end, was producing AsQueryable().
And very surprisingly, it was happening for me from the XUnit Integration Tests call.

I was going wild about why the same problem wasn't happening when calling the same API endpoint via Swagger.


It turned out I had to do an elementary change.
I had to replace the:

using System.Data.Entity;

with:

using Microsoft.EntityFrameworkCore;

In the place where I was calling the LinqKit expression method.

Upvotes: 1

Alexander Myltsev
Alexander Myltsev

Reputation: 499

The problem is as follows.

I have a method:

class Repository {
  public IQueryable<Card> GetKudosCards(Func<Card, bool> predicate) {
    IEnumerable<KudosCard> kudosCards = kudosCardsQuery.Where(predicate);
    return kudosCards
            .OrderByDescending(kc => kc.SendDate)
            .AsQueryable();
  }
}

The problem is that kudosCards has type IEnumerable<KudosCard>. That throws exception. If I change predicate type to Expression<Func<Card, bool> predicate then everything works just fine.

Upvotes: 6

tamasf
tamasf

Reputation: 1078

What is the point of calling AsQueryable? If you compose a query with the extension methods starting from an IQueryable source collection (e.g. DbSet, ObjectSet), the query will be IQueryable too.

The purpose of AsQueryable is to wrap an IEnumerable collection with an IQueryable proxy/adapter that uses a Linq provider that is capable of compiling IQueryable queries into a Linq to Object queries. This can be useful in scenarios when you would like to use inmemory data queries.

Why is the AsQueryable call necessary? What if you just simply remove it?

Update

Okey, now it seems I understand your problem. After a quick look on the ODataQueryOptions.ApplyTo I realized that it just extends the underlying expression tree of the query. You can still use it to run the query in the way you want, however you need a little trick to transform the query back to generic.

IQueryable<Card> cardsQuery =
   dataContext.Cards
    .Where(predicate)
    .OrderByDescending(kc => kc.SendDate);


IQueryable odataQuery = queryOptions.ApplyTo(cardsQuery);

// The OData query option applier creates a non generic query, transform it back to generic
cardsQuery = cardsQuery.Provider.CreateQuery<Card>(odataQuery.Expression);

Task<Card[]> result = cardsQuery.ToArrayAsync();

Upvotes: 9

Related Questions