Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IDbAsyncEnumerable not implemented

I am trying to make a FakeDbContext with a FakeDbSet for unit testing.

But I get the following error (see below). I am extending DbSet so normally IDbAsyncEnumerable should be implemented. And when I implement it, it says that it has no use.

Exception:

System.InvalidOperationException: The source IQueryable doesn't implement IDbAsyncEnumerable. Only sources that implement IDbAsyncEnumerable can be used for Entity Framework asynchronous operations. For more details see http://go.microsoft.com/fwlink/?LinkId=287068.

FakeDbSet class:

public abstract class FakeDbSet<TEntity> : DbSet<TEntity>, IEnumerable<TEntity>, IQueryable, IDbAsyncEnumerable<TEntity> where TEntity : Entity, new() {     #region Private Fields     private readonly ObservableCollection<TEntity> _items;     private readonly IQueryable _query;     #endregion Private Fields      protected FakeDbSet()     {         _items = new ObservableCollection<TEntity>();         _query = _items.AsQueryable();     }      public Expression Expression { get { return _query.Expression; } }      public Type ElementType { get { return _query.ElementType; } }      public IQueryProvider Provider { get { return _query.Provider; } }      public override TEntity Add(TEntity entity)     {         _items.Add(entity);         return entity;     }      public override TEntity Remove(TEntity entity)     {         _items.Remove(entity);         return entity;     }      public override TEntity Attach(TEntity entity)     {         switch (entity.ObjectState)         {             case ObjectState.Modified:                 _items.Remove(entity);                 _items.Add(entity);                 break;              case ObjectState.Deleted:                 _items.Remove(entity);                 break;              case ObjectState.Unchanged:             case ObjectState.Added:                 _items.Add(entity);                 break;              default:                 throw new ArgumentOutOfRangeException();         }         return entity;     }      public override TEntity Create() { return new TEntity(); }      public override TDerivedEntity Create<TDerivedEntity>() { return Activator.CreateInstance<TDerivedEntity>(); }      public override ObservableCollection<TEntity> Local { get { return _items; } }      IEnumerator<TEntity> IEnumerable<TEntity>.GetEnumerator()     {         return _items.GetEnumerator();     }      Type IQueryable.ElementType     {         get { return _items.AsQueryable().ElementType; }     }      Expression IQueryable.Expression     {         get { return _items.AsQueryable().Expression; }     }      IQueryProvider IQueryable.Provider     {         get { return _items.AsQueryable().Provider; }     } 

Here is a gist with the code. In the last file in the gist, that is where the error happens. Gist code

like image 240
kevingoos Avatar asked Oct 10 '14 09:10

kevingoos


Video Answer


2 Answers

In my case the exception was caused by using the wrong ToListAsync extension.

It came from:

using System.Data.Entity; 

instead of

using Microsoft.EntityFrameworkCore; 

Changing the namespace fixed the error.

like image 67
t3chb0t Avatar answered Sep 19 '22 22:09

t3chb0t


Your scenario is explicitly mentioned in the link provided with the exception message (http://go.microsoft.com/fwlink/?LinkId=287068). The missing ingredient is the IDbAsyncQueryProvider that you should return from your Provider property.

Just navigate through the link to arrive at the boilerplate implementation.

Little I can add, I'll just quote the essential phrase:

In order to use asynchronous queries we need to do a little more work. If we tried to use our Moq DbSet with the GetAllBlogsAsync method we would get the following exception:

System.InvalidOperationException: The source IQueryable doesn't implement IDbAsyncEnumerable. Only sources that implement IDbAsyncEnumerable can be used for Entity Framework asynchronous operations. For more details see http://go.microsoft.com/fwlink/?LinkId=287068.

In order to use the async methods we need to create an in-memory DbAsyncQueryProvider to process the async query. Whilst it would be possible to setup a query provider using Moq, it is much easier to create a test double implementation in code. The code for this implementation is as follows:

etc...

like image 38
Hans Passant Avatar answered Sep 18 '22 22:09

Hans Passant