views:

100

answers:

1

I created a LINQ extension as talked about here. But apparently, it does not work with queries on the child. As seen in the code below:

return (from p in repository.GetResources()
                where p.ResourceNames.Any(r => r.Name.WhereIn(arg => arg.Name, "PartialWord"))
                select p).ToList();

What I want to accomplish is that ResourceNames is an EntityCollection, which I need to check if the property 'Name' of the children to see if they contain the word 'PartialWord'.

WhereIn works on like this:

repository.GetResources().WhereIn({CODEHERE});

but when placed on the child, it does not work. Is there a special way to set up my extension. This is it below:

public static class QueryableExtensions
{
    private static Expression<Func<TElement, bool>> GetWhereInExpression<TElement, TValue>(Expression<Func<TElement, TValue>> propertySelector, IEnumerable<TValue> values)
    {
        ParameterExpression p = propertySelector.Parameters.Single();
        if (!values.Any())
            return e => false;

        var equals = values.Select(value => (Expression)Expression.Equal(propertySelector.Body, Expression.Constant(value, typeof(TValue))));
        var body = equals.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal));

        return Expression.Lambda<Func<TElement, bool>>(body, p);
    }

    /// <summary> 
    /// Return the element that the specified property's value is contained in the specifiec values 
    /// </summary> 
    /// <typeparam name="TElement">The type of the element.</typeparam> 
    /// <typeparam name="TValue">The type of the values.</typeparam> 
    /// <param name="source">The source.</param> 
    /// <param name="propertySelector">The property to be tested.</param> 
    /// <param name="values">The accepted values of the property.</param> 
    /// <returns>The accepted elements.</returns> 
    public static IQueryable<TElement> WhereIn<TElement, TValue>(this IQueryable<TElement> source, Expression<Func<TElement, TValue>> propertySelector, params TValue[] values)
    {
        return source.Where(GetWhereInExpression(propertySelector, values));
    }

    /// <summary> 
    /// Return the element that the specified property's value is contained in the specifiec values 
    /// </summary> 
    /// <typeparam name="TElement">The type of the element.</typeparam> 
    /// <typeparam name="TValue">The type of the values.</typeparam> 
    /// <param name="source">The source.</param> 
    /// <param name="propertySelector">The property to be tested.</param> 
    /// <param name="values">The accepted values of the property.</param> 
    /// <returns>The accepted elements.</returns> 
    public static IQueryable<TElement> WhereIn<TElement, TValue>(this IQueryable<TElement> source, Expression<Func<TElement, TValue>> propertySelector, IEnumerable<TValue> values)
    {
        return source.Where(GetWhereInExpression(propertySelector, values));
    } 
}
+1  A: 

Presuming ResourceName.Name is a string:

You don't need any extension for the string version of .Contains() in L2E. (You do need it for the list version in L2E v. 1 only). You should be able to do:

return (from p in repository.GetResources()
        where p.ResourceNames.Any(r => r.Name.Contains("PartialWord"))
        select p).ToList();
Craig Stuntz
How do you know what version of L2E am I using? I get this error with that code:LINQ to Entities does not recognize the method 'Boolean Contains(System.String, System.String, System.StringComparison)' method, and this method cannot be translated into a store expression.
Shawn Mclean
I don't know which version you use, but that doesn't matter, because the `bool Contains(string)` support is the same in all of them. However, you're attempting to use the overload which takes a `StringComparison`, which isn't supported in any version of L2E. You have to use the version which takes a `string` only, as shown in my example. This is equivalent to the sample code in your question, though.
Craig Stuntz