65534

Dynamic LINQ, Select function, works on Enumerable, but not Queryable

I have been fiddling with dynamic LINQ for some time now, but I have yet to learn its secrets.

I have an expression that I want to parse that looks like this:

"document.LineItems.Select(i => i.Credit).Sum();"

During parsing of this I reach a point where I need to call a Select function on LineItems Collection. I am using factory method of Expression.Call:

Expression.Call( typeof(Queryable), "Select", new Type[] { typeof(LineItem), typeof(decimal?) }, expr, Expression.Lambda(expression, new ParameterExpression[] { Expression.Parameter(typeof(LineItem) }));

At this moment

expr: document.LineItems [ICollection<LineItem>] expression: LineItem.Credit [decimal?]

none of which is materialized yet. I am just building Expression Tree at the moment.

Now, the problem:

This Expresssion.Call throws and Exception: "No generic method 'Select' on type 'System.Linq.Queryable' is compatible with the supplied type arguments and arguments";

I resolve it easily by looking for 'Select' in 'System.Linq.Enumerable' instead of 'Queryable' by changing first argument of Expression.Call.

But, that's not quite that I want. I don't want all LineItems hauled in only to calculate Sum(), which would obviously be case with Enumerable. I want Queryable to work.

Also, for the last part of parsing - Sum(), I also need to go with Enumerable Sum(), because Queryable Sum() throws same Exception.

I have checked MSDN, both signatures of 'Select' function are identical, so i really cannot see why would one work and other not.

Any help or pointers would be aprreciated.

Regards,

Answer1:

The problem is that LineItems is an ICollection<LineItem>, while the first parameter to Queryable.Select requires an IQueryable<LineItem>. ICollection<T> only implements IEnumerable<T> which is why it works for Enumerable.Select.

You will need to change the type of expr to be IQueryable<LineItem>.

You should be able to do this with the Queryable.AsQueryable method. The following function creates an expression to sum the credit property values for a given Document instance:

public static Expression<Func<decimal?>> CreateSumLineItemsExpr(Document document) { var docExpr = Expression.Constant(document); var itemsExpr = Expression.Property(docExpr, "LineItems"); Expression<Func<LineItem, decimal?>> selector = i => i.Credit; var queryableExpr = Expression.Call(typeof(Queryable), "AsQueryable", new[] { typeof(LineItem) }, itemsExpr); var selectExpr = Expression.Call(typeof(Queryable), "Select", new[] { typeof(LineItem), typeof(decimal?) }, queryableExpr, selector); var sumExpr = Expression.Call(typeof(Queryable), "Sum", null, selectExpr); return Expression.Lambda<Func<decimal?>>(sumExpr); }

Recommend

  • Trying to develop a new extension method
  • How do I create a core data entry with a queryable array property?
  • Find and remove parameter declaration inside Expression.Block
  • Entity Framework 6 - Npgsql - connection string error
  • LINQ: How to dynamically use an ORDER BY in linq but only if a variable is not string.empty or null
  • How to apply paging specifically to a list which is part of a JSON using asp.net OData protocol
  • How to Unit Test GetNewValues() which contains EntityFunctions.AddDays function
  • How to prevent EF4 from dynamically loading all assemblies
  • EF Code First Foreign Key's
  • Foreign key pointing to Compound Key
  • Issue loading child entity of a parent entity. Unidirectional mapping and 1 to 0..1 relationship wit
  • Will these ActiveXObject and XMLHttpRequest checks apply for any other browser than IE6?
  • Why “propdp” code snippet doesn't use the nameof operator for the name of the registered proper
  • How to map childs/parent class with petapoco?
  • Data Type of Columns in a List - R
  • XGBOOST - DMATRIX
  • Cannot convert a char value to money. The char value has incorrect syntax
  • missing parameter name at index 0 {}
  • Python PIL remove sections of an image based on its colour
  • Is there a chance to get -splash: work for SWT applications that require -XstartOnFirstThread?
  • How to write string.Contains(someText) in expression Tree
  • DependencyObject.AssociatedObject is always null
  • when does setTimeout start executing in a inline
  • include dlls in visual studio c++ 2008
  • How do I register classes by both interface and namespace with Windsor?
  • R Split data.frame using a column that represents and on/off switch
  • Cannot get the UserManager class
  • Unable to decode certificate at client new X509Certificate2()
  • Needing to do .toArray() to get output of mongodb .find() on key name not value
  • Why value captured by reference in lambda is broken? [duplicate]
  • Symfony2: How to get request parameter
  • ORA-29908: missing primary invocation for ancillary operator
  • How can I get HTML syntax highlighting in my editor for CakePHP?
  • How do I configure my settings file to work with unit tests?
  • IndexOutOfRangeException on multidimensional array despite using GetLength check
  • costura.fody for a dll that references another dll
  • Binding checkboxes to object values in AngularJs
  • Observable and ngFor in Angular 2
  • UserPrincipal.Current returns apppool on IIS
  • java string with new operator and a literal