0

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?

4

0 回答 0