tags:

views:

62

answers:

4

I have a business object structured like this:

Country has States, State has Cities

So Country[2].States[7].Cities[5].Name would be New York

Ok, I need to get a list of all the Country objects which have at least 1 City.IsNice == true

How do I get that?

+1  A: 
var result = (from country in db.Countries
             from state in country.States
             from city in state.Cities
             where city.IsNice
             select county).Distinct();
abatishchev
This gives cities and not countries.
brickner
@brickner: have hurried a bit ;)
abatishchev
This query returns the country for *each* nice city... So for instance, if you have 10 nice cities in a country, this query will return the same country 10 times
Thomas Levesque
@Thomas Levesque: Thanks for remark. `Distinct` would help I guess. Would it not?
abatishchev
Yes, but it would be very inefficient...
Thomas Levesque
@Thomas Levesque: Yes, your one is better. But OP asked for LINQ so I did it in 'pure' LINQ
abatishchev
The fact that you're using the query comprehension syntax doesn't make it more "pure" ;). Anyway, the compiler transforms the query syntax into extension method calls
Thomas Levesque
A: 

I would do it in one of two ways:

var selectedCountries = from country in countries
                        from state in country.States
                        from city in state.Cities
                        where city.IsNice
                        select country;

or

var selectedCountries =
    countries.Where(country =>
                    country.States.FirstOrDefault(state =>
                                                  state.Cities.FirstOrDefault(city =>
                                                                              city.IsNice) != null) != null);
brickner
your second one isn't linq it's simply using the same extension methods as LINQ is using
Rune FS
@Rune FS: linQ, not linK ;)
abatishchev
@abatishchev at least I got the second one right :) (thx)
Rune FS
Both are LINQ. LINQ is part of .NET and C# 3.0 has language extensions for it.From Wikipedia (http://en.wikipedia.org/wiki/Language_Integrated_Query):"While LINQ is primarily implemented as a library for .NET Framework 3.5, it also defines a set of language extensions that can be optionally implemented by languages to make queries a first class language construct and provide syntactic sugar for writing queries. These language extensions have initially been implemented in C# 3.0, VB 9.0 and Oxygene, with other languages like F# and Nemerle having announced preliminary support."
brickner
This query returns the country for *each* nice city... So for instance, if you have 10 nice cities in a country, this query will return the same country 10 times
Thomas Levesque
Correct - the first one does. It depends what you want. If you want every country to appear once you can use Distinct() or use the second way I've written (which is more efficient).
brickner
Indeed, I didn't read the second query because I assumed it was the same as the first in a different form. However, you should use Any rather than FirstOrDefault
Thomas Levesque
@brickne: Not sure that extension methods are more efficient then complex LINQ query. I can be wrong but your second approach would cause lookup for 3 times
abatishchev
No, it's efficient just like Any(). I agree that using Any() would work.
brickner
A: 
var result = Countries
    .SelectMany(a => a.States)
    .SelectMany(b => b.Cities)
    .Where(b => b.IsNice == true)
    .ToList();
Neil T.
this returns the cities, not the countries
Thomas Levesque
+3  A: 
var selectedCountries =
    countries.Where(
        co => co.States.Any(
            s => s.Cities.Any(
                ci => ci.IsNice)));

Another option :

var selectedCountries =
    countries.Where(
        co => co.States.SelectMany(s => s.Cities).Any(
            ci => ci.IsNice));
Thomas Levesque