I would like to use Linq to query Entity Framework using a programatically determined Type and array of PropertyInfo. Essentially what we're doing is accepting JSON which is a representation of a database. I can currently retrieve the Type from a string (and PropertyInfo from the Type, if necessary).
Here is the following bit of extracted code I'm using to accomplish this right now:
using (MyEntities db = new MyEntities()) {
Type type = "My.Model.Namespace." + tableNameAsString;
DbSqlQuery records = db.Set(type).SqlQuery(
"SELECT * FROM " + tableNameAsString + " WHERE {0}={1}",
columnToCompare, // string
columnValueToFind // string
);
foreach (object rec in records)
DoSomething(rec);
} // end using
However, raw SQL in this situation doesn't feel right to me. I have made a few attempts at creating Expressions to use with Queryable.Where similar to the following solution found at: How to choose programaticaly the column to be queried by Linq using PropertyInfo? and currently using the fields from my program
var myRecords = Queryable.Where(db.Set(type), someBuiltExpressionHere);
I haven't gotten around to testing out any built Where expressions, because this won't get past the following compiler error:
"The type arguments for method 'System.Linq.Queryable.Where<TSource>
(System.Linq.IQueryable<TSource>, System.Linq.Expressions.Expression<System.Func<TSource,bool>>)'
cannot be inferred from the usage. Try specifying the type arguments explicitly."
To the best of my knowledge (and I'm hoping I'm wrong), because I don't know that type until runtime, I can't supply it to this method.
My question is this: Is there a way to dynamically determine a Where clause based on an Entity Framework "Table" type and a column name determined at runtime, without using straight SQL?
EDIT: Here's another bit of code using expressions that gets me really close to what I need, but I'm still missing a final step or two.
var param = Expression.Parameter(type, "s");
var left = Expression.PropertyOrField(param, pi.Name);
var right = Expression.Constant(true, pi.PropertyType);
var body = Expression.Equal(left, right);
var where = Expression.Lambda<Func<object, bool>>(body, param);
At this point, the following code works:
var records = db.TABLEs.AsQueryable().Where(where).ToList();
The following code does not:
var records = db.Set(type).AsQueryable().Where(where).ToList();
I receive two compiler errors from the second statement.
1. Instance argument: cannot convert from 'System.Linq.IQueryable' to 'System.Linq.IQueryable<My.Model.Namespace.TABLE>'
2. 'System.Linq.IQueryable' does not contain a definition for 'Where' and the best extension method overload 'System.Linq.Queryable.Where<TSource>(System.Linq.IQueryable<TSource>, System.Linq.Expressions.Expression<System.Func<TSource,bool>>)' has some invalid arguments
Any suggestions?