我有一个对象层次结构,排列为大陆>国家>城市。我可以选择一个特定"国家"的所有城市,如下所示。我正在寻找一种方法来合并这两个查询,并在一个查询中获得cityList。
var cities = network.Continents
.SelectMany(continent => continent.Countries)
.Where(ctry => ctry.Id == "country")
.SelectMany(ctry => ctry.Cities);
List<City> cityList = (from c in cities
select new City { Id = c.Id, Name = c.Name }).ToList<City>();
cities中的"c"与cityList中的结构不同,因此第二个查询中的映射也不同。
只需在查询中使用点表示法:
var cities = network.Continents
.SelectMany(continent => continent.Countries)
.Where(ctry => ctry.Id == "country")
.SelectMany(ctry => ctry.Cities)
.Select(cty=> new City{Id = cty.Id, Name = cty.Name }).ToList<City>();
我认为它是可读的,并且没有额外的开销;通常,生成的SQL查询与您自己编写的查询类似,因此这一查询的可读性是它的优势。
您应该能够做到这一点:
var cityList = network.Continents
.SelectMany(continent => continent.Countries)
.Where(ctry => ctry.Id == "country")
.SelectMany(ctry =>
ctry.Cities.Select(c => new City { Id = c.Id, Name = c.Name })
).ToList();
或者:
var cityList =
(from continent in network.Continents
from country in continent.Countries
where country.Id == "country"
from city in country.Cities
select new City { Id = city.Id, Name = city.Name })
.ToList();
发布的选项的另一个替代方案:
var cityList = network.Continents
.SelectMany(continent => continent.Countries)
.Where(ctry => ctry.Id == "country")
.SelectMany(ctry => ctry.Cities,
c => new City { Id = c.Id, Name = c.Name })
.ToList();
SelectMany
的这个重载(在第二个调用中)是C#编译器在查询表达式中使用的重载。注意,如果你想把它写成一个查询表达式,你可以很容易地做到:
var cityList = (from continent in network.Continents
from country in continent.Countries
where country.Id == "country"
from city in country.Cities
select new City { Id = city.Id, Name = city.Name }).ToList();
在LINQ to Objects中,在这种特殊情况下,查询表达式的效率将略低于点表示形式,因为大陆和国家范围变量将向下传播到select子句。。。但我希望任何数据库LINQ提供程序生成的SQL都是相同的,即使在LINQ to Objects中,差异也可能可以忽略不计。
请注意,在调用ToList
时不需要指定类型参数,该类型将被推断为City
。
尝试以下操作:
var cities =
from continent in network.Continents
from country in continent.Countries
from city in country.Cities
where country.Id = "country"
select new City { Id = c.Id, Name = c.Name };