views:

3961

answers:

3

I have an XElement with values for mock data.

I have an expression to query the xml:

Expression<Func<XElement, bool>> simpleXmlFunction = 
    b => int.Parse(b.Element("FooId").Value) == 12;

used in:

var simpleXml = xml.Elements("Foo").Where(simpleXmlFunction).First();

The design time error is:

The type arguments for method 'System.Linq.Enumerable.Where(System.Collections.Generic.IEnumerable, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly'

The delegate supplied to Where should take in an XElement and return a bool, marking if the item matches the query, I am not sure how to add anything more to the delegate or the where clause to mark the type.

Also, the parallel method for the real function against the Entity Framework does not have this issue. What is not correct with the LINQ-to-XML version?

+7  A: 

Don't make simpleXmlFunction an Expression<Func<XElement, bool>>. Make it a Func<XElement, bool>. That's what's expected as a delegate of .Where.

Func<XElement, bool> simpleXmlFunction =
     new Func<XElement, bool>(b => int.Parse(b.Element("FooId").Value) == 12);
David Morton
Why does it work for Entity.Where then?
blu
The .Where implementation for IQueryable<T> is different than the .Where implementation for IEnumerable<T>.
David Morton
ahh I see it, thanks for the clarification.
blu
+2  A: 

I think the full answer includes the previous answer, David Morton's comment, and an updated code snippet:

The .Where implementation for IQueryable is different than the .Where implementation for IEnumerable. IEnumerable.Where expects a:

Func<XElement, bool> predicate

You can compile the function from the expression you have by doing:

Expression<Func<XElement, bool>> simpleXmlExpression = 
    b => int.Parse(b.Element("FooId").Value) == 12; 

Func<XElement, bool> simpleXmlFunction = simpleXmlExpression.Compile();

var simpleXml = xml.Elements("Foo").Where(simpleXmlFunction).First();

This will allow you to look at the expression tree generated and to use the compiled form to query the xml collection.

blu
A: 

@blu - Thanks for the further explanation! I've been learning Linq over the past week, and found myself unable to make the LINQKit PredicateBuilder class work with a List of custom objects. Yours is the first post I've come across that made reference to the .Compile() function. I created a complex query and applied it correctly, but kept getting the same error as the OP. Once I changed myObjectList.Where(predicate).ToList() to myObjectList.Where(predicate.Compile()).ToList() everything worked great. :)