I'm dialing the number. Any Entity Framework Extension Method that uses Expression Trees

c# entity-framework expression-trees

Question

I have looked at a few examples on this page (Utilizing an Expression to Call a Method) and on page (zzz-9) but I am unable to determine the correct method call or object type for Any() for the following query. The property call seems to be working for me, but not the IEnumerable portion of the child property.
The parent of billmaps lu, billing map set lu, is specified as an association in the Entity Framework.

I use expression trees because I need to be able to define the query using 1-n at runtime. Billmaps lu = SelectMany(p). clauses with a where(predicate) Therefore, I reasoned that if I could create the expression trees, I could manage all of the many possibilities I had for this system.

var myResults = ctx.billing_map_set_lu
                   .Where(p => p.billmaps_lu.Any(b => b.billmap_columnname == "templatesittings_key" &&  b.billmap_columnvalue == 428264))
                                   SelectMany(p => p.billmaps_lu)
                   .Where (b =>b.billmap_columnname =="locations_key" && b.billmap_columnvalue == 12445)
                                   Select(z => z.billing_map_set_lu);

I've made a number of efforts utilizing the aforementioned examples...

ParameterExpression bms = Expression.Parameter(typeof(billmaps_lu));
Expression left1 = Expression.Property(bms, typeof(billmaps_lu).GetProperty("billmap_columnname"));
Expression right1 = Expression.Constant("templatesittings_key", typeof(string));
Expression InsideAny1 = Expression.Equal(left1, right1);
Expression left2 = Expression.Property(bms, typeof(billmaps_lu).GetProperty("billmap_columnvalue"));
Expression right2 = Expression.Constant(428264, typeof(int));
Expression InsideAny2 = Expression.Equal(left2, right2);
Expression myWhereClause1 = Expression.AndAlso(InsideAny1, InsideAny2);

The stuff mentioned above seems to be alright, however when I attempt to. Any It seems like I can't find the appropriate property or method to extract the appropriate items. (I feel as if I am working on a physics issue where I am using the incorrect units.) Since I am somewhat new to expression trees, I am hopeful that there is a simple item I am missing. To attempt to show you where my brain is at and how someone can point me in the correct path, I have attached non-working code.

MethodInfo method = typeof(Enumerable).GetMethods().Where(m => m.Name == "Any" && m.GetParameters().Length == 2).Single().MakeGenericMethod(typeof(billing_map_set_lu).GetProperty("billmaps_lu").PropertyType);
ParameterExpression billMapSetParameter = Expression.Parameter(typeof(billing_map_set_lu), "p");
ParameterExpression billMaps = Expression.Parameter(typeof(billmaps_lu), "p1");
var myFunction = Expression.Lambda<Func<billmaps_lu, bool>>(Expression.Call(method, Expression.Property(billMapSetParameter, typeof(billing_map_set_lu).GetProperty("billmaps_lu")), myWhereClause1), billMaps)
1
2
5/23/2017 12:24:40 PM

Accepted Answer

I should note that I don't have any finished, functional code.

2 issues.

The first issue is most likely:

ParameterExpression billMapSetParameter = Expression.Parameter(typeof(billing_map_set_lu), "p");

You don't need that parameter in:

Expression.Lambda<Func<billmaps_lu, bool>>(Expression.Call(method, Expression.Property(**billMapSetParameter**, typeof(billing_map_set_lu).GetProperty("billmaps_lu")), myWhereClause1), billMaps)

You should be fine to go after changing the billMapSetParameter to the billMaps ParameterExpression. You are using the PropertyExpression to ask the ParameterExpression to get your billMapSet for you.

The second issue is that, in my opinion, the Where clause should be supplied as a ConstantExpression of type Expression. Func<>>. . Any method requires two inputs, the second of which is an expression. (Or is it simply a Func? can't recall).

var whereExpression = Expression.Lambda<.Func<.billmaps_lu, bool>>(myWhereClause1, bms);
var ce = Expression.Constant(whereExpression)

Pass the ce back into the original location where "myWhereClause1" is.

Hopefully that will work.

That should be changed to SHOW MI ZEH CODEZ.

public class Foo
{
    public List<string> Strings { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        Func<Foo, bool> func =
            a => a.Strings.Any(b => b == "asdf");

        // b => b == "asdf";
        var bParameter = Expression.Parameter(typeof (string));
        var asdfConstant = Expression.Constant("asdf");
        var compare = Expression.Equal(bParameter, asdfConstant);
        var compareExpression = Expression.Lambda<Func<string, bool>>(compare, bParameter);
        var ceCompareExpression = Expression.Constant(compareExpression.Compile());

        // a => a.Strings.Any(compareExpression)
        var parameter = Expression.Parameter(typeof (Foo));

        var foosProperty = Expression.Property(parameter, typeof (Foo).GetProperty("Strings"));
        MethodInfo method = typeof(Enumerable).GetMethods().Where(m => m.Name == "Any" && m.GetParameters().Length == 2).Single().MakeGenericMethod(typeof(string));

        var anyMethod = Expression.Call(method, foosProperty, ceCompareExpression);

        var lambdaExpression = Expression.Lambda<Func<Foo, bool>>(anyMethod, parameter);

        // Test.
        var foo = new Foo {Strings = new List<string> {"asdf", "fdsas"}};

        Console.WriteLine(string.Format("original func result: {0}", func(foo)));
        Console.Write(string.Format("constructed func result: {0}", lambdaExpression.Compile()(foo)));

        Console.ReadKey();
    }
}
0
12/8/2016 9:09:37 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow