创建仅在运行时已知的列名称的where子句

时间:2014-02-11 15:03:59

标签: c# linq entity-framework linq-to-entities

我正在寻找上述实体框架问题的解决方案。

我想要实现的基本概念是:

string columnName = "whatever";
var data = context.MyObject.Where(x => x.columnName == value);

我环顾四周,为Linq找到了解决这个问题的解决方案,但它不能与LINQ to Entities一起使用。

var data = context.MyObject.Where(
    p => p.GetType().GetProperty(columnName)
                    .GetValue(p, null) as string == value);

抛出异常:

  

LINQ to Entities无法识别方法'System.Object GetValue(System.Object,System.Object [])'方法,并且此方法无法转换为商店表达式。

我也想避免使用SQL或SQL之类的命令。有人做过/见过类似的东西吗?

编辑:已经开展了更多工作并且已经到了这一步。

public IQueryable<TEntity> DynamicWhere(string _property, IList<string> 

_compare)
        {
            IQueryable<TEntity> query = m_context.Set<TEntity>();

            var parameterExp = Expression.Parameter(typeof(TEntity));
            var propertyExp = Expression.Property(parameterExp, _property);
            MethodInfo method = typeof(IList<string>).GetMethod("Contains");
            var someValue = Expression.Constant(_compare, typeof(IList<string>));
            var containsMethodExp = Expression.Call(propertyExp, method, someValue);

            return query.Where(Expression.Lambda<Func<TEntity, bool>>(containsMethodExp, parameterExp));
        }

在MethodInfo行返回null

之前,事情看起来很好

1 个答案:

答案 0 :(得分:3)

LINQ to Entities需要Expression<Func<T, bool>>。您可以通过lambda表达式指定此表达式,也可以在运行时构造此表达式。

var parameter = Expression.Parameter(typeof(T));
var expression = Expression.Lambda<Func<T, bool>>(
      Expression.Equal(Expression.MakeMemberAccess(parameter, typeof(T).GetProperty("MyProperty")),
      Expression.Constant(value)), parameter);

var result = queryable.Where(expression);

编辑:这些表达式树可能会变得复杂,编写它们的代码很难读取。如何检索它们的一个好方法是创建一个方法,该方法接受表达式树并试验编译器为几个lambda表达式创建的内容。