AutoMapper unable to cast TestDbAsyncEnumerable to IQueryable

I've implemented the TestDbAsync fakes from https://msdn.microsoft.com/en-us/library/dn314429(v=vs.113).aspx and I want to be able to use AutoMapper to project to a different type before calling the Async EF methods (ToListAsync, CountAsync, etc.).

I get a cast exception in ProjectionExpression.To

Example code that throws the exception.

_userRepository.GetAll().OrderBy(x => x.Id).ProjectTo<User>.ToListAsync();

This works fine in a non-test scenario, but when I mock the DbSet using the TestDbAsyncEnumerable I get

: Unable to cast object of type 'Namespace.TestDbAsyncEnumerable`1[UserEntity]' to type 'System.Linq.IQueryable`1[User]'.

Right now to get around this I have to ProjectTo after the call to the Async EF extensions. Is there any way to keep the ProjectTo call before the EF extensions?

Reference code:

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

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

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

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

    IQueryProvider IQueryable.Provider => new TestDbAsyncQueryProvider<T>(this);
}

public static Mock<DbSet<T>> ToAsyncDbSetMock<T>(this IEnumerable<T> source)
        where T : class
    {

        var data = source.AsQueryable();

        var mockSet = new Mock<DbSet<T>>();

        mockSet.As<IDbAsyncEnumerable<T>>()
            .Setup(m => m.GetAsyncEnumerator())
            .Returns(new TestDbAsyncEnumerator<T>(data.GetEnumerator()));

        mockSet.As<IQueryable<T>>()
            .Setup(m => m.Provider)
            .Returns(new TestDbAsyncQueryProvider<T>(data.Provider));

        mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(data.Expression);
        mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(data.ElementType);
        mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());

        return mockSet;
    }

Edit your TestDbAsyncQueryProvider<>.CreateQuery() so that it returns the right type of the expression passed by ProjectTo<>.

Here is my sample implementation.

public IQueryable CreateQuery(Expression expression)
{
    switch (expression)
    {
        case MethodCallExpression m:
            {
                var resultType = m.Method.ReturnType; // it shoud be IQueryable<T>
                var tElement = resultType.GetGenericArguments()[0];
                var queryType = typeof(TestDbAsyncEnumerable<>).MakeGenericType(tElement);
                return (IQueryable)Activator.CreateInstance(queryType, expression);
            }
    }
    return new TestDbAsyncEnumerable<TEntity>(expression);
}

https://gist.github.com/masaedw/95ab972f8181de6bbe48a20ffe9be113

I have written also unit test. It's working.

https://github.com/masaedw/AutoMapper/blob/TestDbAsync/src/IntegrationTests/MockedContextTests.cs

Automapper无法将TestDbAsyncEnumerable转换为IQueryable, AutoMapper unable to cast TestDbAsyncEnumerable to IQueryable. 发布于 2020 -06-22 04:01:23. I've implemented the TestDbAsync fakes from� Thanks so much for the awesome tool! Similar to in this StackOverflow item, I am not able to use AutoMapper's ProjectTo when using the generated FakeDbContext, but it works fine with the real one.

I ran into this same problem, in addition to the accepted answer you might also have the generic version of CreateQuery like I do - I fixed that too like this:

public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
    var queryType = typeof(TestDbAsyncEnumerable<>).MakeGenericType(typeof(TElement));
    return (IQueryable<TElement>)Activator.CreateInstance(queryType, expression);
}

The type is being provided by TElement, so its a simplier implementation on the generic version.

AutoMapper/AutoMapper, AutoMapper unable to cast TestDbAsyncEnumerable to IQueryable. 来源: link 标签:c#entity-frameworkautomapper 更新时间: 2020-05-29� at DataTables.Queryable.DataTablesQueryProvider`1.CreateQuery(Expression expression) at AutoMapper.QueryableExtensions.ProjectionExpression.Select(IQueryable source, LambdaExpression lambda) in C:\projects\automapper\src\AutoMapper\QueryableExtensions\ProjectionExpression.cs:line 89 at System.Linq.Enumerable.Aggregate[TSource,TAccumulate

I was getting this same error in my tests after upgrading from Automapper 6.0.2 to 6.1.1. Downgrading back to 6.0.2 fixed the issue.

Not sure if this is a regression or a breaking change in Automapper. I haven't had time to pursue it further than reviewing the change log and github issues. Nothing jumps out.

AutoMapper невозможно привести TestDbAsyncEnumerable к , InvalidCastException when mapping IQueryable multiple times. We map InvalidCastException: 'Unable to cast object of type 'AutoMapper. System.InvalidCastException: Unable to cast object of type 'AModel' to type 'BModel'. at AutoMapper.MappingEngine.Map[TSource,TDestination](TSource source) This comment has been minimized. Sign in to view

By using a combination of the two mentioned answers above helped me use .ProjectTo across our unit tests.

In my TestDbAsyncQueryProvider implementation I replaced these two methods:

public IQueryable CreateQuery(Expression expression)
{
    switch (expression)
    {
        case MethodCallExpression m:
            {
                var resultType = m.Method.ReturnType; // it shoud be IQueryable<T>
                var tElement = resultType.GetGenericArguments()[0];
                var queryType = typeof(TestDbAsyncEnumerable<>).MakeGenericType(tElement);
                return (IQueryable)Activator.CreateInstance(queryType, expression);
            }
    }
    return new TestDbAsyncEnumerable<TEntity>(expression);
}

public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
    var queryType = typeof(TestDbAsyncEnumerable<>).MakeGenericType(typeof(TElement));
    return (IQueryable<TElement>)Activator.CreateInstance(queryType, expression);
}

It works fine with the latest EF6 as of today.

AutoMapper не может привести TestDbAsyncEnumerable к , Expected behavior ProjectTo () could call internally the IQueryable _source's - to-cast-testdbasyncenumerable-to-iqueryable/45769447#45769447. to force everyone use reflection if AutoMapper is able to call the generic� But for some reason, AutoMapper is trying to map the resolver: System.InvalidCastException : Unable to cast object of type 'Newgistics.Fulfillment.AutoStore.Synq

in case someone on his Entities has other object, the ProjectTo will crash or throw an exception with Null Reference Object.

Solution for that, is to make sure your Entity has all its objects initialized with a default() or something.

Answer found on the last comment / answer here -> Why is Automapper.ProjectTo() throwing a null reference exception?

P.S thanks for the IAsyncQueryProvider implementation :)

AutoMapper无法将TestDbAsyncEnumerable强制转换为IQueryable, Unable to cast object of type 'Namespace.TestDbAsyncEnumerable`1[UserEntity] ' to type 'System.Linq.IQueryable`1[User]'. Прямо сейчас, чтобы обойти это,� The Cast<TResult>(IQueryable) method generates a MethodCallExpression that represents calling Cast<TResult>(IQueryable) itself as a constructed generic method. It then passes the MethodCallExpression to the CreateQuery(Expression) method of the IQueryProvider represented by the Provider property of the source parameter.

Queryable Extensions — AutoMapper documentation, Unable to cast object of type 'Namespace.TestDbAsyncEnumerable`1[UserEntity] ' to type 'System.Linq.IQueryable`1[User]'. Теперь, чтобы обойти это, мне� AutoMapper doesn't know how to map IQueryables. I'm not sure how it would either, IQueryables include a query provider that translates expression trees to an IEnumerable. AutoMapper falls back to IEnumerable, which IQueryable inherits. Are you trying to use the LINQ projection? Or translate two expression trees?

c#, AutoMapper unable to cast TestDbAsyncEnumerable to IQueryable 假货,我希望能够使用AutoMapper投影到其他类型之前调用Async EF� Unable to cast object of type HashSet`1[T] to List`1[T] after upgrading to AutoMapper 6.2.* #2436 Closed ristogod opened this issue Nov 28, 2017 · 2 comments

For example, you can not rely on the ToString() override of the Item class to such as OData, a generic DTO is returned through an IQueryable controller action. "Cannot implicitly convert type 'System.Linq.IQueryable<AnonymousType#1>' to 'System.Collections.Generic.IEnumerable<Product>'. An explicit conversion exists (are you missing a cast?) "I get this error, when I try to use LINQ to SQL to select a particular column, instead of returning the entire Northwind database.

Comments
  • Nice :) Good to see someone tracking the root cause.
  • I like your product! Thanks!
  • Saved my day : P
  • Didn't think to downgrade. We ended up abstracting away the EF calls behind an interface for testing.
  • As @Masayuki Muto discovered below, the problem is in the mock provider. If anyone is interested in contributing, we could also work around it inside AM.