I'm trying to create search functionality across a couple of tables, following the pattern in Creating dynamic queries with entity framework
I have 3 tables:
People:
pk ID
varchar FirstName
varchar LastName
fk AddressMap_ID
AddressMap:
pk ID
Address:
pk ID
varchar StreetName
varchar StreeNumber
fk AddressMap_ID
Multiple people can live at one address. I pass in a Search model, and populate the results property:
public class Search
{
public string streetname { get; set; }
public string streetnumber { get; set; }
public string fname { get; set; }
public string lname { get; set; }
public IEnumerable<Results> results { get; set; }
}
public class Results
{
public int AddressID { get; set; }
public string StreetNumber { get; set; }
public string StreetName { get; set; }
public IEnumerable<PeopleResults> people { get; set; }
}
public class PeopleResults
{
public int personID { get; set; }
public string First { get; set; }
public string Last { get; set; }
}
This works if I filter on an address, or name + address:
public void GetResults(Search model)
{
Entities _context;
_context = new Entities();
var addr = from a in _context.Addresses
select a;
addr = addr.Where(filter => filter.StreetNumber == model.streetnumber);
addr = addr.Where(filter => filter.StreetName == model.streetname);
addr = from a in addr
group a by a.AddressMap_ID into addrs
select addrs.FirstOrDefault();
var ppl = from p in addr.SelectMany(p => p.AddressMap.People) select p;
ppl = ppl.Where(filter => filter.FirstName.StartsWith(model.fname));
ppl = ppl.Where(filter => filter.LastName.StartsWith(model.lname));
model.results = from a in addr
select new Results
{
AddressID = a.ID,
StreetName = a.StreetName,
StreetNumber = a.StreetNumber,
people = from p in ppl
select new PeopleResults
{
First = p.FirstName,
Last = p.LastName
}
};
}
But if I just try to filter on a name, it returns a cartesian join - every single address with all of the people that matched.
There are 3 ways to search: filtering on address only, filter on address + name, or filter on name only.
So if someone search for "123 Main", the results should be
123 Main St SticksVille Joe Smith
Jane Smith
Mary Smith
123 Main St Bedrock Fred Flintstone
Wilma Flintstone
A search for "J Smith 123 Main" should return just:
123 Main St SticksVille Joe Smith
Jane Smith
And a search for just "J Smith" should return:
123 Main St SticksVille Joe Smith
Jane Smith
456 Another St Sometown Jerry Smith