Reputation: 6740
I am trying to figure out a way to search through a User's contact details.
User can have more than one Contact
Here is my code:
_usersRep.Find(r=>(string.IsNullOrEmpty(vm.PhoneNumber)
|| r.UserContacts
.Select(o => o.TelephoneNo)
.Contains(vm.PhoneNumber))
This should bring back me the user that any of its contact contains the PhoneNumber that I pass it to it. I actually tried to find where it should be equal but I could not get it worked.
I have checked on the database that this user has a contact object and that contac object phone number is the one that I search for but it does not bring me the user.
The relationship between User
and UserContacts
is one to many.
I also would like to ignore the search filter if the text is empty? But when I do not type anything it brings me all users.
Upvotes: 1
Views: 108
Reputation: 1185
Assume that vm.PhoneNumber
is your search filter, add !
to String.IsNullOrEmpty
check and change ||
to &&
_usersRep.Find(r=>(!string.IsNullOrEmpty(vm.PhoneNumber)
&& r.UserContacts
.Select(o => o.TelephoneNo)
.Contains(vm.PhoneNumber))
Upvotes: 0
Reputation: 3231
The reason why you are getting all of the users when the search string is because of this
_usersRep.Find(r=>(string.IsNullOrEmpty(vm.PhoneNumber) || ... )
If the phone number string is null or empty then the find will always return true, giving you all of the users
you want
if(!string.IsNullOrEmpty(vm.PhoneNumber))
_usersRep.Find(r=> ... )
For the other problem, try trimming your string
if(!string.IsNullOrEmpty(vm.PhoneNumber))
_usersRep.Find(r=>r.UserContacts
.Select(o => o.TelephoneNo)
.Contains(vm.PhoneNumber.Trim()))
Besides those changes don't notice anything else that should be giving you problems.
Upvotes: 0
Reputation: 3769
I think you are looking for something like:
_usersRep.Where(r => r.UserContacts.Any(uc => uc.TelephoneNo == vm.PhoneNumber))
So restricting which users are returned (Where clause) based on whether the user has Any usercontacts with a matching number.
EDIT multiple conditions:
_usersRep.Where(r => r.UserContacts.Any(uc => uc.TelephoneNo == vm.PhoneNumber &&
uc.EmailAddress == vm.EmailAddress)) // etc
So the logic is, for each UserContact we test, if ALL the conditions are true in the lambda expression, then it passes the predicate, in which case as we are using the Any test, the userRep is selected. Hope this makes sense!
OK so if some of the fields can legitimately be empty, we should make sure the filter is defined if we do a compare, so combining in some nested ORs
works here:
_usersRep.Where(r => r.UserContacts.Any(uc =>
(String.IsNullOrEmpty(vm.PhoneNumber) || uc.TelephoneNo == vm.PhoneNumber) &&
(String.IsNullOrEmpty(vm.EmailAddress) || uc.EmailAddress == vm.EmailAddress)))
Note that if all fields in vm are blank, this will bring back everything, as there is no restriction. If you don't want this, you should probably check before calling this query.
Explanation
Just to make it clear how this works. If we take the basic clause for each field:
(String.IsNullOrEmpty(vm.PhoneNumber) || uc.TelephoneNo == vm.PhoneNumber)
We are saying if part A
or B
is true, then for this field we have a match. Note that the ||
operator evaluates A
first, and only evaluates B
if A
is false. So, in plain English, if String.IsNullOrEmpty(vm.PhoneNumber)
is true
(ie if the user doesn't enter query text for this field) then it is a match, no matter what the PhoneNumber
s actually are. So therefore we only test uc.TelephoneNo == vm.PhoneNumber
when something was specified for vm.PhoneNumber
So the above determines that for a single field we have a match (either because the user didn't enter a query for this field, or because they did, and the strings match). Now we use the &&
to ensure that every field we are checking is a match based on the above test.
Now because we do String.IsNullOrEmpty
first for every field in our filter, if this is true for every field, based on the above logic, everything is a match. This makes semantic sense as well - if you don't enter any terms to restrict the search, you would expect to receive everything.
If the above is a problem in your case, as I said before I would check this before you execute the query, and tell the user that they must enter at least one search term to restrict the search.
Upvotes: 3