Reputation: 53
I have a Person and PersonType object where a Person has one to many PersonTypes. A PersonType can be Accountant, Consultant etc.
Person table has the following columns: 'firstname' | 'lastname' | 'email' | 'phonenumber'
PersonType table has the following columns: 'name' | 'description'
I've created a search mechanism using LINQ in C# but the problem is that I get a wrong result due to an issue with a LINQ constraint. Suppose we have two Person records where the first record is a Consultant and the other record is Consultant and Accountant meaning it has to child objects.
Note. My search is case insensitive.
Suppose my search text is 'co'. Then I don't want the result to be 3 records. Now it returns the first person and two instances of the second person due to two matches of 'co' for Accountant and Consultant for the second Person.
Of course I can go through the result and filter out duplicates but it would be nice to have it one query.
Many thanks for your input.
Here is the Linq:
private IList<PersonViewModel> SearchAll(string searchCriteria)
{
var result = System.Web.HttpContext.Current.Session["Persons"] as IList<PersonViewModel>;
if (result != null)
{
var v = (from a in result
from b in a.PersonTypes
where
a.FirstName.CaseInsensitiveContains(searchCriteria) ||
a.LastName.CaseInsensitiveContains(searchCriteria) ||
a.Email.CaseInsensitiveContains(searchCriteria) ||
a.PhoneNumber.CaseInsensitiveContains(searchCriteria) ||
b.Name.CaseInsensitiveContains(searchCriteria)
select a);
return v.ToList();
}
return result;
}
Upvotes: 1
Views: 266
Reputation: 109252
One little strategy may be very helpful in problems with queries and search conditions:
Only query the entities you need and do nothing but where
.
You need PersonViewModel
s. By joining in PersonTypes
(from - from
is a GroupJoin
) also PersonTypes
become accessible to the end result. So if you only query the entities you need, there should be one, and only one, from
:
var v = from a in result
Now what should the where
be? The conditions for PersonViewModel
are clear, but what about PersonTypes
? Loosely defined in plain language, where at least one of their PersonTypes
contains "co". In LINQ that amounts to:
var v = from a in result
where a.FirstName.CaseInsensitiveContains(searchCriteria)
|| a.LastName.CaseInsensitiveContains(searchCriteria)
|| a.Email.CaseInsensitiveContains(searchCriteria)
|| a.PhoneNumber.CaseInsensitiveContains(searchCriteria)
|| a.PersonTypes.Any(pt => pt.Name.CaseInsensitiveContains(searchCriteria));
Now you don't need Distinct
because there's no join
that duplicates results.
Upvotes: 1
Reputation: 305
you can get result as following
var v=result?.Where(p=>p.PersonTypes.Select(t=>t.Name).Contains(searchCriteria) ||
p.FirstName.CaseInsensitiveContains(searchCriteria) ||
p.LastName.CaseInsensitiveContains(searchCriteria) ||
p.Email.CaseInsensitiveContains(searchCriteria) ||
p.PhoneNumber.CaseInsensitiveContains(searchCriteria) ||)?.ToList();
Upvotes: 1
Reputation: 249
Salam i think you can do it like that
v.GroupBy(person => person.id)
.Select(g => g.First())
.ToList();
Upvotes: 0