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
 IEnumberable<CustomerSports> //properties: CustomerID, SportsID
 IEnumberable<CustomerLocation> //properties: CustomerID, LocationID
 IEnumberable<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.

其他提示

One method of doing this, if i understood what you were after. Allows multiple sports, and multiple pets, or none.

        var contacts = from cust in customer
                       join sport in sports on cust.CustomerID equals sport.CustomerID into multisport from sport in multisport.DefaultIfEmpty()
                       join loc in location on cust.CustomerID equals loc.CustomerID
                       join pet in pets on cust.CustomerID equals pet.CustomerID into multipet from pet in multipet.DefaultIfEmpty()

                       select new
                       {
                           cust.CustomerID,
                           multisport,
                           loc.LocationID,
                           multipet
                       };
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top