This has been bugging me for a while since I'm trying to come up with an optimized way of querying this.
So lets say I have 3 cross reference tables that share a common column, where that common column will do a final join on a main table that contains more info.
For example:
Let's say I have the following:
Customers //properties: ID, Name, Address
IEnumerable<CustomerSports> // properties: CustomerID, SportsID
IEnumerable<CustomerLocation> // properties: CustomerID, LocationID
IEnumerable<CustomerPets> // properties: CustomerID, PetsID
So I can make queries such as:
Give me a list of customers that plays lacrosse, football, soccer (CustomerSports
) and have dogs and cats (CustomerPets
), that live in New York (CustomerLocation
). The lookup tables can be nullable, so Customers could play sports, but have no pets.
Then when I get a list of customers, I'll join that common column (CustomerID
) on the customer table to retrieve the ID, Name, and Address.
I was thinking about having the customer table join on each lookup, and then doing a union to fetch the list of customers, but I don't know if that is the correct way of doing it.
As long as you have setup your design correctly then each Customer
should have a Sports
collection, a Pets
collection and a Locations
(unless this last one is a one-to-one join?).
If those relationships are setup, then you can query as follows:
var sports = new string[] { "lacrosse", "football", "soccer" };
var pets = new string[] { "cat", "dog" };
var locations = new string[] { "new york" };
var sportyPetLoversInNewYors = db.Customers
.Where(cust => sports.All(sport => cust.Sports.Any(custSport => custSport.Name == sport)))
.Where(cust => pets.All(pet => cust.Pets.Any(custPet => custPet.Name == pet)))
.Where(cust => locations.All(loc => cust.Locations.Any(custLoc => custLoc.Name = loc)))
// could customise the select here to include sub-lists or whatever
.Select();
This assumes that you only want people that have all 6 criteria. If you want people that like at least one of those sports, with at least one of those pets, and (assuming you used more than one location) are in at least one of those locations, the Where
expression would change like the following
.Where(cust => cust.Sports.Any(custSport => sports.Contains(custSport.Name)))
Let me know if you need further explanation.