Эффективно?С точки зрения написанного кода, хорошо, но мы будем называть это «чисто».С точки зрения исполнения, это не тот вопрос, который вам следует задавать в данный момент.Сосредоточьтесь на том, чтобы выполнить работу в понятном коде, а затем " мчитесь на лошадях ", чтобы увидеть, действительно ли вам нужно улучшить его.запрос, который не изменяет исходные последовательности.Вы присваиваете отфильтрованные последовательности обратно свойствам, что противоречит принципам LINQ.Тег показывает, что вы используете Entity Framework, так что это определенно не очень хорошая идея, потому что он использует свои собственные типы коллекций.
Чтобы ответить на ваш вопрос, метод расширения SelectMany
зацикливается на проецируемой последовательности.Когда он переводится в запрос к базе данных, он переводится в объединение.
dbSet.Countries
.Where(c => c.Names.Length > 5)
.SelectMany(c => c.Provinces)
.Where(p => p.Name.Length > 5)
.SelectMany(p => p.Cities)
.Where(ci => ci.Name.Length > 5)
.Select(ci => ci.Name);
Это даст вам названия всех городов, в которых названия стран, провинций и городов длиннее 5 символов.
Но это только дает вам названия городов.Если вы хотите знать каждый уровень информации, методы расширения сложны в использовании, потому что вы должны проецировать «прозрачные идентификаторы» на каждом этапе, и это может стать довольно загроможденным.Пусть компилятор сделает это за вас, используя синтаксис LINQ.
from c in dbSet.Countries
where c.Name.Length > 5
from p in c.Provinces
where p.Name.Length > 5
from ci in p.Cities
where ci.Name.Length > 5
Это будет делать то же самое, что и выше, за исключением того, что все переменные диапазона передаются через выражение, поэтому вы можете сделать это:
select new
{
CountryName = c.Name,
ProvinceName = p.Name,
CityName = ci.Name
};
... или что вы хотите сделать с c
, p
и ci
.