Question

I work on project that use some dynamic linq query to an entities. i have huge amount of case and to avoid code duplication i refactoring to a method. But using method which isn't in store expression will result to throw an exception. One of solutions is to encapsulate method result into an expression which can be interpreted by linq to entitie query.

Consider that code :

parentExpression = x => x.child.Any(y=>IsGoodChild(y,childType, childSize));

private bool IsGoodChild(child c, int childType, int childSize){
     return c.type == childType && c.size == childSize;
}

"parentExpression " is predicate of type "Parent" of my EF. This code throw an exception, "IsGoodChild" method return a boolean and can't be interpreted by linq to Entities.

So, i would like something like this :

parentExpression = x => x.child.AsQueryable().Any(IsGoodChild(childType, childSize));

private System.Linq.Expression.Expression<Func<child, bool>> IsGoodChild(int childType, int childSize){
     return  ????
}

So how can i do "IsGoodChild(...)" can work even if which not take x.child attribute ? Thx for advance


Re,

I try something, when i write lambda directly in expression like this :

parentExpression = x => x.child.Any(y=>y.type == childType && y.size == childSize);

i used extract method from resharper and generate it this :

private Expression<Func<child,Boolean>> IsGoodChildFunctional(Int32 childType, Int32 childSize)
{
    return c => c.type == childType && c.size == childSize; 
}

But i also have .NET Framework Data Provider error 1025' error ...

Was it helpful?

Solution 2

Create a static generic method which will return an Expression. The Expression is built by using factory methods.

public static Expression<Func<TTargetObject,Boolean>> IsGoodChildFunctional<TTargetObject>(Int32 childType, Int32 childSize)
{
            var e = Expression.Parameter(typeof(TTargetObject), "e");
            var childTypeMember = Expression.MakeMemberAccess(e, typeof(TTargetObject).GetProperty("childType"));
            var childSizeMember = Expression.MakeMemberAccess(e, typeof(TTargetObject).GetProperty("childSize"));
            var  childTypeConstant = Expression.Constant(childType, childType.GetType());
            var  childSizeConstant = Expression.Constant(childSize, childSize.GetType());
            BinaryExpression b;
            BinaryExpression bBis;
            Expression<Func<TTargetObject, bool>> returnedExpression;
            b = Expression.Equal(childTypeMember , childTypeConstant );
            bBis2 = Expression.Equal(childSizeMember, c2);
            var resultExpression = Expression.AndAlso(b, bBis);
            returnedExpression = Expression.Lambda<Func<TTargetObject, bool>>(resultExpression , e);
            return returnedExpression;
}

It is called like this:

var predicat = IsGoodChildFunctional<child>(childType, childSize);
parentExpression = x => x.child.Any(predicat);

OTHER TIPS

In this case the compiler is clever, given an anonymous method it will switch between an expression tree or a compiled lambda depending on the declared type. The following should work:

private Expression<Func<child,Boolean>> 
IsGoodChildFunctional(Int32 childType, Int32 childSize)
{
    return c => c.type == childType && c.size == childSize; 
}

which would be used like so:

parentExpression = x => x.child
                         .AsQueryable()
                         .Any(IsGoodChildFunctional(childType,childSize));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top