如何将Linq转换为实体查询到表达式树?

时间:2014-04-25 18:41:34

标签: c# linq linq-to-entities expression-trees

说我有以下查询如何获得基本表达式树?

MyContext.Items.Select(i=>i.Color);

我想得到这个的表达式树,以便我可以使用表达式树动态设置选择的属性(所以我可以选择颜色,大小,重量,价格等。)

我认为我与以下内容很接近,但我一直在收到错误:

        IQueryable<Item> query = c.Items;


        string SelctField = "Color";
        ParameterExpression pe = Expression.Parameter(typeof(Item), "i");
        Expression SelectProperty = Expression.Property(pe, SelctField);

        MethodCallExpression Select = Expression.Call(
            typeof(Queryable),
            "Select",
            new Type[] {query.ElementType},
            pe,
            Expression.Lambda<Func<Item, string>>(SelectProperty, pe));

        var result =  query.Provider.CreateQuery<string>(Select);

以上结果

No generic method 'Select' on type 'System.Linq.Queryable' is compatible with the
supplied type arguments and arguments. No type arguments should be provided if the 
method is non-generic

所以我尝试删除那个重载并继续得到不同的错误。

我也在调试模式下获取此内部表达式文本,但不了解如何转换它。

    .Call System.Linq.Queryable.Select(
    .Call .Constant<System.Data.Entity.Core.Objects.ObjectQuery`1[Inventory_Ordering_And_Reporting.Item]>(System.Data.Entity.Core.Objects.ObjectQuery`1[Inventory_Ordering_And_Reporting.Item]).MergeAs(.Constant<System.Data.Entity.Core.Objects.MergeOption>(AppendOnly))
    ,
    '(.Lambda #Lambda1<System.Func`2[Inventory_Ordering_And_Reporting.Item,System.Nullable`1[System.String]]>))

    .Lambda      #Lambda1<System.Func`2[Inventory_Ordering_And_Reporting.Item,System.Nullable`1[System.String]]>(Inventory_Ordering_And_Reporting.Item $i)
{
    $i.Color
}

2 个答案:

答案 0 :(得分:2)

不完全确定这是否适用于数据库提供程序,但希望因为它纯粹基于表达式。

public class Item
{
    public string Blah { get; set; }
    public string Foo { get; set; }
}

[TestMethod]
public void Test()
{
    string propertyName = "Blah";
    System.Linq.Expressions.ParameterExpression arg = System.Linq.Expressions.Expression.Parameter(typeof(Item), "x");

    PropertyInfo pi = typeof(Item).GetProperty(propertyName,
    BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
    System.Linq.Expressions.Expression expr = System.Linq.Expressions.Expression.Property(arg, pi);
    System.Linq.Expressions.LambdaExpression lambda = System.Linq.Expressions.Expression.Lambda(expr, arg);
    System.Linq.Expressions.Expression<Func<Item, string>> funcExpression = (System.Linq.Expressions.Expression<Func<Item, string>>)lambda;

    List<Item> test = new List<Item> { new Item { Blah = "Test", Foo = "Another" } };
    IQueryable<Item> query = test.AsQueryable();
    var result = query.Select(funcExpression).ToList();
}

答案 1 :(得分:1)

你可以使用反射:

    public static void DoStuff(string fieldName)
    {
        List<test> ban = new List<test>();
        ban.Add(new test() { number = 40, notNumber = "hi" });
        ban.Add(new test() { number = 30, notNumber = "bye" });


        var result = ban.Select(item => item.GetType().GetField(fieldName).GetValue(item));
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
    class test
    {
        public int number;
        public string notNumber;
    }

此示例适用于select应检查字段是否存在的字段,如果不存在则查找属性。