Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to cast object of type 'System.Linq.Expressions.InstanceMethodCallExpressionN' to type 'System.Linq.Expressions.LambdaExpression' #13

Closed
abatishchev opened this issue Feb 2, 2015 · 9 comments
Labels

Comments

@abatishchev
Copy link

I have a service performing some aggregation which I want make plugable::

public class AverageValueCalculator : IValueCalculator
{
    public decimal? GetValue(IQueryable<Order> orders)
    {
        return orders.Average(o => (decimal?)o.Amount);
    }
}

And here's the query I want to plug this service in:

IQueryable<Order> orders = ordersRepository.GetAll();
var q = from o in orders
        group o by o.OrderDate into g
        select new
        {
            OrderDate = g.Key,
            AggregatedAmount = g.AsQueryable()
                                .Average(x => (decimal?)x.Amount) // here
        };

So I used LinqKit:

Expression<Func<IQueryable<Order>, decimal?>> expression = orders => _calc.GetValue(orders);

var q = from o in orders
        group o by o.OrderDate into g
        select new
        {
            OrderDate = g.Key,
            AggregatedAmount = expression.Compile()(g.AsQueryable())
        };

But it throws an exception:

Unable to cast object of type 'System.Linq.Expressions.InstanceMethodCallExpressionN' to type 'System.Linq.Expressions.LambdaExpression'.
   at LinqKit.ExpressionExpander.VisitInvocation(InvocationExpression iv)
   at LinqKit.ExpressionVisitor.Visit(Expression exp)
   at LinqKit.ExpressionVisitor.VisitExpressionList(ReadOnlyCollection`1 original)
   at LinqKit.ExpressionVisitor.VisitNew(NewExpression nex)
   at LinqKit.ExpressionVisitor.Visit(Expression exp)
   at LinqKit.ExpressionVisitor.VisitLambda(LambdaExpression lambda)
   at LinqKit.ExpressionVisitor.Visit(Expression exp)
   at LinqKit.ExpressionVisitor.VisitUnary(UnaryExpression u)
   at LinqKit.ExpressionVisitor.Visit(Expression exp)
   at LinqKit.ExpressionVisitor.VisitExpressionList(ReadOnlyCollection`1 original)
   at LinqKit.ExpressionVisitor.VisitMethodCall(MethodCallExpression m)
   at LinqKit.ExpressionExpander.VisitMethodCall(MethodCallExpression m)
   at LinqKit.ExpressionVisitor.Visit(Expression exp)
   at LinqKit.Extensions.Expand(Expression expr)
   at LinqKit.ExpandableQueryProvider`1.System.Linq.IQueryProvider.CreateQuery[TElement](Expression expression)
   at System.Linq.Queryable.Select[TSource,TResult](IQueryable`1 source, Expression`1 selector)
   at MyProject.Services.OrderService.<GetInventoryValuesForOrder>d__14.MoveNext()

Is is fixable on my side, or requires investigation on your side? Thanks!

@Maximaximum
Copy link

I've got the same problem! What is the cause for it? Any help appreciated

@abatishchev
Copy link
Author

Any thoughts on this, please? No queries containing grouping work.

@scottksmith95
Copy link
Owner

I am not sure on this particular issue. I didn't write the original code but am officially maintaining it on GitHub. If you could troubleshoot more and potentially provide a fix, I will gladly merge the change.

@Thorium
Copy link
Collaborator

Thorium commented Apr 14, 2015

Hello,

You use Compile if you want to compile your expression to C#. But you use .AsExpandable() and .Invoke() if you want to compile your expression to SQL via LINQKit. Like this:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Data.Entity;
    using System.Linq;
    using System.Linq.Expressions;
    using LinqKit;

    public class Order
    {
        [Key] public int Id  { get; set; }
        [Required] public int Amount { get; set; }
        [Required] public DateTime OrderDate { get; set; }
    }

    /// <summary> Some simple EF DBContext item for this example </summary>
    public class MyDbContext : DbContext
    {
        static MyDbContext(){ Database.SetInitializer<MyDbContext>(null); }
        public MyDbContext() : base("Server=localhost;Database=test;Integrated Security = True;") { }
        public DbSet<Order> Orders { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Expression<Func<IQueryable<Order>, decimal?>> expression = orders => orders.Average(o => (decimal?)o.Amount);

            using (var context = new MyDbContext())
            {
                IQueryable<Order> orders = context.Orders;
                var q = from o in orders.AsExpandable()
                        group o by o.OrderDate into g
                        select new
                        {
                            OrderDate = g.Key,
                            AggregatedAmount = expression.Invoke(g.AsQueryable())
                        };
                //ToList or ToListAsync:
                q.ToList().ForEach(Console.WriteLine);
                Console.ReadLine();
            }
        }
    }

The expression LINQ can be outside of the MyDbContext.
And the thing here is that you get only single SQL so not hammering the database. The generated SQL from this example would be something like this:

    SELECT 
        1 AS[C1], 
        [GroupBy1].[K1]
    AS[OrderDate], 
        [GroupBy1].[A1]
    AS[C2]
    FROM(SELECT
    [Extent1].[OrderDate] AS[K1],
    AVG( CAST( [Extent1].[Amount] AS decimal(19,0))) AS[A1]
    FROM[dbo].[Orders]
    AS[Extent1]
    GROUP BY[Extent1].[OrderDate]
        )  AS[GroupBy1]

@abatishchev
Copy link
Author

Can you please reopen? I forgot about this ticket. I'll investigate and post an update

@scottksmith95
Copy link
Owner

Sure thing

@scottksmith95 scottksmith95 reopened this May 28, 2015
@Thorium
Copy link
Collaborator

Thorium commented Oct 3, 2015

@abatishchev, Is this still valid?

@abatishchev
Copy link
Author

Sorry about this, changed the job, stopped using EF, really don't have time to take a look on this.

@giovinazzo-kevin
Copy link

fuck

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants