【问题标题】:Maybe a Really simple, Dynamic Linq To Entities Select statement?也许是一个非常简单的 Dynamic Linq To Entity Select 语句?
【发布时间】:2014-06-10 10:12:16
【问题描述】:

我想要的基本上是能够做到以下(以下是伪代码)

string SelectField = cb1.Name.Substring(2);
MyContext.Items.Select(x=>x.SelectField )

我尝试了以下方法:

string SelectField = cb1.Name.Substring(2);
ParameterExpression pe = Expression.Parameter(typeof(Item), "p");
var expr = Expression.Lambda(Expression.Property(pe, SelectField), pe);

query = MyContext.Items.Select(p=>expr)

但它给了我错误:

The LINQ expression node type 'Lambda' is not supported in LINQ to Entities.

这可能吗?我只是希望能够根据我的组合框的选择来选择单个实体属性。

【问题讨论】:

  • 属性多吗?如果没有,可能切换不同的查询会更容易。
  • 另外,动态 linq 库可以帮助你:dynamiclinq.codeplex.com
  • @Gusman 那是我的,但大约有 15 个属性,即使更少,我也想知道是否有一种更简单的方法,不需要重复的代码,只需进行一次更改跨度>
  • 看看我之前评论中的库,允许从字符串创建 linq 查询。
  • @Gusman 我真的不想在库上导入另一个依赖项,查看它的源代码,它看起来使用表达式树的方式与我尝试使用它们的方式相同,也许它会帮我弄清楚我做错了什么。

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


【解决方案1】:

我能够使用以下代码获得我想要的结果(与我最初的尝试没有太大区别)

string SelectField = cb1.Name.Substring(2);
ParameterExpression pe = Expression.Parameter(typeof(Item), "p");
Expression expr = Expression.Lambda(Expression.Property(pe, SelectField), pe);

Expression<Func<Item, string>> expression = (Expression<Func<Item, string>>)expr;

var query = MyContext.Items.Select(expression);

我所缺少的只是 Func 行。它现在可以按我的意愿工作了。

【讨论】:

    【解决方案2】:

    好的,所以对于这种类型的解决方案,您可能需要进行大量反射才能使其动态工作。

    string SelectField = cb1.Name.Substring(2);
    ParameterExpression pe = Expression.Parameter(typeof(Item), "p");
    

    首先,您必须在不知道完整返回类型的情况下调用 lambda 方法。返回类型为Expression&lt;Func&lt;Item, ?&gt;&gt;(问号是属性类型的占位符。

    var propertyType = typeof(Item).GetProperty(SelectField).GetGetMethod().ReturnType;
    var lambdaMethodParamType = typeof(Func<,>).MakeGenericType(typeof(Item), propertyType);
    var lambdaMethod = typeof(Expression).GetMethods().First(x => x.Name == "Lambda" && x.IsGenericMethod).MakeGenericMethod(lambdaMethodParamType);
    var expr = lambdaMethod.Invoke(null, new object[] { Expression.Property(pe, SelectField), new ParameterExpression[] { pe } });
    

    然后我们必须以类似的方式调用 select 方法,因为直到运行时才知道属性类型。

    var selectMethod = typeof(Queryable).GetMethods().First(x => x.Name == "Select").MakeGenericMethod(typeof(Item), propertyType);
    var query = (IQueryable)selectMethod.Invoke(null, new object[] { MyContext.Items, expr });
    

    我不知道您对查询变量做了什么,因此我目前无法提供任何进一步的指导。同样,在此示例中,直到运行时我们才知道集合中将包含什么类型,因为它是属性值的集合。

    仅供参考:我选择正确 lambda 和 select 的方法完全是 hack。您确实应该创建一个更强大的搜索方法来更完整地检查签名,以确保您找到了所需的正确方法。如果你有更多时间需要,我可以提供一个更好的例子。

    【讨论】:

    • 感谢您的意见,我能够通过在我最初的尝试中添加 1 行来实现目标。请参阅我的最终解决方案的答案。我根据您之前的评论和您的部分答案得到了这个答案。使用您的答案中的信息是否可以让我将其设为通用?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多