MrEff
MrEff

Reputation: 89

Composing LINQ Expressions

I've read a bunch of articles on putting LINQ expressions together, but they only seem to cover and's and or's. I have this solution implemented:

http://blogs.msdn.com/b/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspx

How do I write this code so that it works?

Expression<Func<Crop, bool>> chooseOranges = crop => crop.IsOrange;
Expression<Func<Farm, bool>> selectFarm = farm => farm.HasCows;

selectFarm = selectFarm.And(farm => farm.Crops.Any(chooseOranges);

It compiles, but at runtime it throws a .NET 1025 error. If I replaced chooseOranges with the literal text it would work, but chooseOranges is built piece by piece with business logic. It seems like the code I linked above relies on the various Expression.Foo() functions, but I couldn't find one that would help.

Upvotes: 1

Views: 786

Answers (2)

Chris Pitman
Chris Pitman

Reputation: 13104

Use LinqKit's ability to evaluate nested expressions and return a single expression usable by any provider that would support the same expression written out:

Expression<Func<Crop, bool>> chooseOranges = crop => crop.IsOrange;
Expression<Func<Farm, bool>> selectFarm = farm => farm.HasCows;    
Expression<Func<Farm, bool>> combined = (farm) => selectFarm.Invoke(farm) && farm.Crops.Any(inner => chooseOranges.Invoke(inner));
combined = combined.Expand();

Upvotes: 2

Amy B
Amy B

Reputation: 110221

I would write it like this:

Expression<Func<Crop, bool>> chooseOranges = crop => crop.IsOrange;  
Expression<Func<Farm, bool>> selectFarm = farm => farm.HasCows;  

IQueryable farmQuery = GetQuery();
farmQuery = farmQuery.Where(selectFarm);
farmQuery = farmQuery.Where(farm => farm.Crops.Any(chooseOranges); 

Each row must meet both criteria to be in the result, so that's And.

For Or, I did that over there.

Upvotes: 1

Related Questions