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