0

I am new to lambda expressions and I am having issues trying to figure out how to represent my entity framework query in one. I also could be wrong and there is just a better way to do what I want. If this is true please let me know. My scenario is I have an advanced search screen where you could choose to search bu name, customer number, or phone number. You can search by more than 1 if you want. I am using Entity Framework as my backend and have repositories set up for my tables. Below is the code I am trying to use

Func<Parties, bool> exp;

exp = null;

if (vm.CustomerNumberCriteria != null)
{
    custID = Convert.ToInt32(vm.CustomerNumberCriteria);
    exp = o => o.ID == custID;
}


if (vm.NameCriteria != null)

    exp += o => o.LastName.Contains(vm.NameCriteria) || o.FirstName.Contains(vm.NameCriteria) || o.MiddleName.Contains(vm.NameCriteria) || o.Designation.Contains(vm.NameCriteria);

if (vm.PhoneNumberCriteria != null)

    exp += o => o.CentralPhoneNumbers.Any(child => child.PhoneNumber == vm.PhoneNumberCriteria);

//TODO set tempresults
tempresults = custs.All.Where(exp).ToList();

My issue is it seems to treat this like an and and I need results if there is a match on any of the search criteria.

Thanks

1 Answer 1

3

There are two big problems here. Firstly, you're using delegates, not expression trees - which means your entire table is going to be pulled back to the client and filtered there. You want Expression<Func<Parties, bool>>.

Now, if you want to build up "or" expression trees, the simplest approach is to use PredicateBuilder:

var predicate = PredicateBuilder.False<Parties>();

if (vm.CustomerNumberCriteria != null)
{
    custID = Convert.ToInt32(vm.CustomerNumberCriteria);
    predicate = predicate.Or(o => o.ID == custID);
}

if (vm.NameCriteria != null)
{
    custID = Convert.ToInt32(vm.CustomerNumberCriteria);
    predicate = predicate.Or(o => o.LastName.Contains(vm.NameCriteria) /* etc */)
}

if (vm.PhoneNumberCriteria != null)
{
    predicate = predicate.Or(o => o.CentralPhoneNumbers.Any
                     (child => child.PhoneNumber == vm.PhoneNumberCriteria));
}

tempresults = custs.All.Where(predicate).ToList();
Sign up to request clarification or add additional context in comments.

4 Comments

Expression<Parties, bool> should be Expression<Func<Parties, bool>>, right?
@hvd: Yup, typo, sorry. Fixed.
For anyoen looking at this answer you have to download LinqKit to get PredicateBuilder. It was quite easy to do through Nuget. Your solution worked great for me. The only thing I had to change from your example was on the last line I had to say custs.All.AsExpandable.Where but I think that si because my data was from entity framework.
@DaveWade: You don't have to download LinqKit - the complete source code is in the middle of the page I linked to. You can download LinqKit of course, but you can also just take the source code from the page. Glad it worked though :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.