none
PredicateBuilder and IDbAsyncEnumerable RRS feed

  • Question

  • Hello,

    I was working with Entity Framework 6 in an existing code which was calling "ToListAsync" and was ok before a small change...

    Due to a need of a "search conditions engine", I have used the famous PredicateBuilder from Jospeh Albahari (http://www.albahari.com/nutshell/predicatebuilder.aspx) and a call to "AsExpandable()" from his LinqKit was needed.

    Thanks to his PredicateBuilder, I can easily manage all my conditions in a proper code but that only work with a ToList without async...
    If I try to call the ToListAsync after an usage of AsExpandable, I have the following exception:

    "System.InvalidOperationException : The source IQueryable doesn't implement
    IDbAsyncEnumerable..."

    I can totally understand the exception and the source code of LinqKit is open but I can't find any example of implementation of IDbAsyncEnumerable.

    Do you know where I can find that?

    That will be used by the most used method in my application so I really need the code from LinqKit to have async possibilities...

    Thanks!
    Tuesday, November 5, 2013 9:44 AM

Answers

  • Hello,

    I see your response only now but I found the same link yesterday, thank you!

    Thanks to this link, I have try the following code:

    public class ExpandableQuery<T> : IQueryable<T>, IOrderedQueryable<T>, IOrderedQueryable, IDbAsyncEnumerable<T>
    {
    	ExpandableQueryProvider<T> _provider;
    	IQueryable<T> _inner;
    
    	internal IQueryable<T> InnerQuery { get { return _inner; } } 
    
    	internal ExpandableQuery (IQueryable<T> inner)
    	{
    			_inner = inner;
    			_provider = new ExpandableQueryProvider<T> (this);
    	}
    
    	Expression IQueryable.Expression { get { return _inner.Expression; } }
    	Type IQueryable.ElementType { get { return typeof (T); } }
    	IQueryProvider IQueryable.Provider { get { return _provider; } }
    	public IEnumerator<T> GetEnumerator () { return _inner.GetEnumerator (); }
    	IEnumerator IEnumerable.GetEnumerator () { return _inner.GetEnumerator (); }
    	public override string ToString() { return _inner.ToString(); }
    			
    	public IDbAsyncEnumerator<T> GetAsyncEnumerator()
    	{
    		return new ExpandableDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
    	}
    	
    	IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
    	{
    		return GetAsyncEnumerator();
    	}
    }

    It's a class which is coming from the source code of LinqKit: I added the implementation of IDbAsyncEnumerable<T> (the two GetAsyncEnumerator methods).

    And I have created a new class:

    public class ExpandableDbAsyncEnumerator<T> : IDbAsyncEnumerator<T>
    {
    	private readonly IEnumerator<T> _inner;
    	
    	public ExpandableDbAsyncEnumerator(IEnumerator<T> inner)
    	{
    		_inner = inner;
    	}
    	
    	public void Dispose()
    	{
    		_inner.Dispose();
    	}
    	
    	public Task<bool> MoveNextAsync(CancellationToken cancellationToken)
    	{
    		return Task.FromResult(_inner.MoveNext());
    	}
    	
    	public T Current
    	{
    		get { return _inner.Current; }
    	}
    	
    	object IDbAsyncEnumerator.Current
    	{
    		get { return Current; }
    	}
    }

    This new class (used by the GetAsyncEnumerator method) has been created thanks to your link.

    I can now use the method AsExpandable and the ToListAsync(), that works very well! But I am not 100% sure of my code (because there is not a lot of example of implementation of this interface and its usage)

    Do you think that is ok?

    Thanks!

    Wednesday, November 6, 2013 8:36 AM
  • Hello,

    Entity Framework 6 introduced a set of extension methods that can be used to asynchronously execute a query. Examples of these methods include ToListAsync, FirstAsync, ForEachAsync, etc.

    Because Entity Framework queries make use of LINQ, the extension methods are defined on IQueryable and IEnumerable. However, because they are only designed to be used with Entity Framework we may receive the following error if we try to use them on a LINQ query that isn’t an Entity Framework query.

    Whilst the async methods are only supported when running against an EF query, we may want to use them in we unit test when running against an in-memory test double of a DbSet.

    For how to achieve this scenario see the 'Testing with async queries' section in links below:

    http://msdn.microsoft.com/en-us/data/dn314429#async

    In order to use the async methods we need to create an in-memory DbAsyncQueryProvider to process the async query.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, November 6, 2013 2:17 AM
    Moderator

All replies

  • Hello,

    Entity Framework 6 introduced a set of extension methods that can be used to asynchronously execute a query. Examples of these methods include ToListAsync, FirstAsync, ForEachAsync, etc.

    Because Entity Framework queries make use of LINQ, the extension methods are defined on IQueryable and IEnumerable. However, because they are only designed to be used with Entity Framework we may receive the following error if we try to use them on a LINQ query that isn’t an Entity Framework query.

    Whilst the async methods are only supported when running against an EF query, we may want to use them in we unit test when running against an in-memory test double of a DbSet.

    For how to achieve this scenario see the 'Testing with async queries' section in links below:

    http://msdn.microsoft.com/en-us/data/dn314429#async

    In order to use the async methods we need to create an in-memory DbAsyncQueryProvider to process the async query.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, November 6, 2013 2:17 AM
    Moderator
  • Hello,

    I see your response only now but I found the same link yesterday, thank you!

    Thanks to this link, I have try the following code:

    public class ExpandableQuery<T> : IQueryable<T>, IOrderedQueryable<T>, IOrderedQueryable, IDbAsyncEnumerable<T>
    {
    	ExpandableQueryProvider<T> _provider;
    	IQueryable<T> _inner;
    
    	internal IQueryable<T> InnerQuery { get { return _inner; } } 
    
    	internal ExpandableQuery (IQueryable<T> inner)
    	{
    			_inner = inner;
    			_provider = new ExpandableQueryProvider<T> (this);
    	}
    
    	Expression IQueryable.Expression { get { return _inner.Expression; } }
    	Type IQueryable.ElementType { get { return typeof (T); } }
    	IQueryProvider IQueryable.Provider { get { return _provider; } }
    	public IEnumerator<T> GetEnumerator () { return _inner.GetEnumerator (); }
    	IEnumerator IEnumerable.GetEnumerator () { return _inner.GetEnumerator (); }
    	public override string ToString() { return _inner.ToString(); }
    			
    	public IDbAsyncEnumerator<T> GetAsyncEnumerator()
    	{
    		return new ExpandableDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
    	}
    	
    	IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
    	{
    		return GetAsyncEnumerator();
    	}
    }

    It's a class which is coming from the source code of LinqKit: I added the implementation of IDbAsyncEnumerable<T> (the two GetAsyncEnumerator methods).

    And I have created a new class:

    public class ExpandableDbAsyncEnumerator<T> : IDbAsyncEnumerator<T>
    {
    	private readonly IEnumerator<T> _inner;
    	
    	public ExpandableDbAsyncEnumerator(IEnumerator<T> inner)
    	{
    		_inner = inner;
    	}
    	
    	public void Dispose()
    	{
    		_inner.Dispose();
    	}
    	
    	public Task<bool> MoveNextAsync(CancellationToken cancellationToken)
    	{
    		return Task.FromResult(_inner.MoveNext());
    	}
    	
    	public T Current
    	{
    		get { return _inner.Current; }
    	}
    	
    	object IDbAsyncEnumerator.Current
    	{
    		get { return Current; }
    	}
    }

    This new class (used by the GetAsyncEnumerator method) has been created thanks to your link.

    I can now use the method AsExpandable and the ToListAsync(), that works very well! But I am not 100% sure of my code (because there is not a lot of example of implementation of this interface and its usage)

    Do you think that is ok?

    Thanks!

    Wednesday, November 6, 2013 8:36 AM
  • Glad to hear that you found the solution.

    I think as long as the new class is created follow the TestingDemo, it would be ok.

    And it is appreciate that you share the class to us. I think someone else who is headache for this issue will great thankful for this if they find this.

    Cheers.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, November 6, 2013 9:29 AM
    Moderator
  • Worthy of a login and reply -- excellent add. For once, it wasn't stackoverflow with the answer. 

    Travis Whidden

    Friday, August 7, 2015 11:26 PM