Come posso convertire Linq in Entities Query nell'albero delle espressioni?

c# expression-trees linq linq-to-entities

Domanda

Dite che ho la seguente domanda come posso ottenere l'albero delle espressioni di base?

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

Voglio ottenere l'albero delle espressioni di questo in modo che possa quindi utilizzare l'albero delle espressioni per impostare dinamicamente quale proprietà viene selezionata (quindi posso scegliere Colore, Dimensione, Peso, Prezzo ecc.)

Penso di essere vicino a quanto segue, ma continuo a ricevere errori:

        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);

I risultati sopra riportati

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

così ho provato a rimuovere quel sovraccarico e continuo a ricevere errori diversi.

Ottengo anche questo testo di espressioni interne in modalità di debug, ma non capisco come convertirlo.

    .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
}

Risposta accettata

Non è del tutto sicuro se questo funzionerà con il provider DB, ma si spera poiché si basa esclusivamente sull'espressione.

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();
}

Risposta popolare

Puoi usare la riflessione:

    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;
    }

Questo esempio è per i campi che la select dovrebbe probabilmente controllare per vedere se il campo esiste e se non lo è, allora cerca una proprietà.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché