2

Say, I have these properties which are overridden in a derived class.

protected virtual Expression<Func<TEntity, long>> GetIDExpr { get; }
protected virtual Expression<Func<TEntity, string>> GetNameExpr { get; }
protected virtual Expression<Func<TEntity, long>> GetValueExpr { get; }

Now say I have this class

public class MyData
{
    public long ID { get; set; }
    public string Name { get; set; }
    public long Value { get; set; }
}

Now, in the base class, how would I make an Expression<Func<TEntity, MyData>> that, when invoked, will populate each field and allow me to create a method that returns IEnumerable<MyData>?

I'd like to avoid using Invoke, as I'd only like these 3 fields to be selected from the database.

Note: For the sake of this example, treat each property as if every time it is called it returns the same instance of the Expression, rather than creating a new instance each time.

Edit:

Here was my attempt, which isn't working:

public IEnumerable<MyData> GetAllData(IQueryable<TEntity> table) {
    ParameterExpression parameter = Expression.Parameter(typeof(TEntity), "obj");

    List<MemberBinding> bindings = new List<MemberBinding>  {
        Expression.Bind(typeof(MyData).GetProperty("ID"), GetIDExpr.Body),
        Expression.Bind(typeof(MyData).GetProperty("Name"), GetNameExpr.Body),
        Expression.Bind(typeof(MyData).GetProperty("Value"), GetValueExpr.Body),
    };

  var selector = Expression.MemberInit(Expression.New(typeof(MyData).GetConstructor(Type.EmptyTypes)), bindings);

  var getBar = Expression.Lambda<Func<TEntity, MyData>>(selector, parameter);

  return table.Select(getBar);
}

Here I get an ArgumentException when the query is executed, saying

The parameter 'obj' was not bound in the specified LINQ to Entities query expression.

I assume this means using .Body for the value expression wouldn't work as there is no longer a parameter. However, if I don't use .Body, I get an Exception on the .Bind method

Argument types do not match

Connell
  • 13,925
  • 11
  • 59
  • 92

1 Answers1

0

I don't know of a way to assemble an expression tree from other expression trees in a lambda expression, so I think you'll have to build the tree programmatically. This MSDN article (How to: Use Expression Trees to Build Dynamic Queries) shows how to use the expression tree API to build an expression tree.

In this case, you'd need a new expression followed by three property assignments; I don't think you can do that in an expression tree. You could get around that by creating a constructor that assigns the properties.

phoog
  • 42,068
  • 6
  • 79
  • 117
  • Only parameterless constructors are supported in LINQ to Entities. I knew that would happen. Any chance I can combine Expression.Assign statements? – Connell Mar 21 '12 at 17:42