0

I'm trying to pass lambda expressions and a type to my DAL. I have this statement:

(entities).GetType().GetMethod("Where")

"entities" is the Table of entities on the DataContext.

When I run the statement I get a null even though Linq.Table inherits IQueryable.

Anyone have an idea?

Here is the entire method:

public object GetResultSet(Dictionary<Type, Func<object, bool>> values)
{
    using (ICSDataContext db = DataContextFactory.CreateDataContext<ICSDataContext>(DataContexts.ICS))
    {
        foreach (var entry in values)
        {
            var property = db.GetType().GetProperty(entry.Key.Name + "s");
            IQueryable entities = (IQueryable)property.GetValue(db, null);                     

            var whereMethod = (entities).GetType().GetMethod("Where")
                        .MakeGenericMethod(Type.GetType(entry.Key.AssemblyQualifiedName));


            return whereMethod.Invoke(entities, new object[] { entry.Value });    
        }
    }

    return null;
}

Thanks

Matyas
  • 1,122
  • 5
  • 23
  • 29
Eitan
  • 1,434
  • 6
  • 21
  • 53
  • 4
    1) `Where` is an [_extension_ method](https://msdn.microsoft.com/en-us/library/bb383977.aspx), so it's not defined on the interface _directly_ and thus can't be found by `GetMethod`. 2) What do you intend to _do_ with the method? You shouldn't need to "find" the `Where` method using reflection. – D Stanley Sep 11 '15 at 14:07
  • Better question is why are you using reflection? Chances are what ever your trying to do can be done though expression trees or dynamic linq instead – johnny 5 Sep 11 '15 at 14:10
  • I want to pass a type and a lambda expression and have it run against the DB. I would pass the entity type and the Func returning a boolean variable and I'd like it to query the DB – Eitan Sep 11 '15 at 14:11
  • So the goal is not to find something with reflection, but to select something using `Where` from a DB? I don't really understand why are you using reflection here. – Matyas Sep 11 '15 at 14:26
  • 1
    I could be going about this all wrong :) I want to create a query language on the frontend and then convert it into a db call. I don't know the entity type or conditions at compile time so I'm using reflection. Is there a better way? – Eitan Sep 11 '15 at 14:29
  • @Eitan: Would it be better to construct a SQL expression instead and pass the expression to the database and read the results? – Matyas Sep 11 '15 at 14:36
  • Actually I think that's a better idea or entity sql but I'm just curious how I'd be able to create my own query language...something simple like 'subscriber.firstName = Matyas' and convert it to lambda expressions and passit to the DBContext – Eitan Sep 11 '15 at 14:38

2 Answers2

0

As an alternative you could do something like

db.Set<Type>()

which will return you the DBSet of the appropriate type, with Where accessible without reflection. Also you may want to use Expression> rather than Func, expressions work on queryables where as funcs work on enumerables. If you pass a func into a Where clause it pulls the entire dbset down and processes it in memory.

Typed expressions are also a little easier to work with (intellesence, type checking).

Expression<Func<User,bool>> filter = c=>c.FirstName == "Bob";

As another alternative you can look into System.Linq.Dynamic, ScottGu has a write up on it here. The article and the code are old, but it works with EF 6. It allows things like

.Where("CategoryId=2 and UnitPrice>3")
Miniver Cheevy
  • 1,667
  • 2
  • 14
  • 20
0

From answer by LukeH under here:

var where1 = typeof(Queryable).GetMethods()
             .Where(x => x.Name == "Where")
             .Select(x => new { M = x, P = x.GetParameters() })
             .Where(x => x.P.Length == 2
                         && x.P[0].ParameterType.IsGenericType
                         && x.P[0].ParameterType.GetGenericTypeDefinition() == typeof(IQueryable<>)
                         && x.P[1].ParameterType.IsGenericType
                         && x.P[1].ParameterType.GetGenericTypeDefinition() == typeof(Expression<>))
             .Select(x => new { x.M, A = x.P[1].ParameterType.GetGenericArguments() })
             .Where(x => x.A[0].IsGenericType
                         && x.A[0].GetGenericTypeDefinition() == typeof(Func<,>))
             .Select(x => new { x.M, A = x.A[0].GetGenericArguments() })
             .Where(x => x.A[0].IsGenericParameter
                         && x.A[1] == typeof(bool))
             .Select(x => x.M)
             .SingleOrDefault();

Then this:

 var gmi = where1.MakeGenericMethod(typeof(T));
Community
  • 1
  • 1
user326608
  • 2,210
  • 1
  • 26
  • 33