LINQ Join с несколькими предложениями From
Когда я пишу запросы LINQ на C#, я знаю, что могу выполнить соединение, используя join
ключевое слово. Но что делает следующее?
from c in Companies
from e in c.Employees
select e;
Книга LINQ Я говорю, что это тип соединения, но не правильное соединение (которое использует join
ключевое слово). Так что же это за тип соединения?
4 ответа
Множественные операторы "from" считаются составными linq-утверждениями. Они как вложенные операторы foreach. Страница MSDN перечисляет отличный пример здесь
var scoreQuery = from student in students
from score in student.Scores
where score > 90
select new { Last = student.LastName, score };
это утверждение можно переписать так:
SomeDupCollection<string, decimal> nameScore = new SomeDupCollection<string, float>();
foreach(Student curStudent in students)
{
foreach(Score curScore in curStudent.scores)
{
if (curScore > 90)
{
nameScore.Add(curStudent.LastName, curScore);
}
}
}
Это будет переведено в SelectMany()
вызов. По сути, это перекрестное соединение.
Джон Скит рассказывает об этом в своем блоге, как часть серии Edulinq. (Прокрутите вниз до " Вторичные" предложения ".")
Код, который вы перечислили:
from c in company
from e in c.Employees
select e;
... создаст список каждого сотрудника для каждой компании в company
переменная. Если сотрудник работает в двух компаниях, он будет включен в список дважды.
Единственное "соединение", которое может произойти здесь, это когда вы говорите c.Employees
, В провайдере, поддерживаемом SQL, это будет переводиться во внутреннее соединение Company
стол к Employee
Таблица.
Тем не менее, двойнойfrom
Конструкция часто используется для выполнения "соединений" вручную, например так:
from c in companies
from e in employees
where c.CompanyId == e.CompanyId
select e;
Это будет иметь тот же эффект, что и код, который вы разместили, с потенциальными тонкими различиями в зависимости от того, что employees
переменная содержит Это также будет эквивалентно следующему join
:
from c in companies
join e in employees
on c.CompanyId equals e.CompanyId
select e;
Если вы хотите декартово произведение, вы можете просто удалить where
пункт. (Чтобы это чего-то стоило, вы, вероятно, захотите изменить select
хоть и немного тоже.)
from c in companies
from e in employees
select new {c, e};
Этот последний запрос даст вам все возможные комбинации компании и сотрудника.
Весь первый набор объектов будет объединен со всем вторым набором объектов. Например, следующий тест пройдет...
[TestMethod()]
public void TestJoin()
{
var list1 = new List<Object1>();
var list2 = new List<Object2>();
list1.Add(new Object1 { Prop1 = 1, Prop2 = "2" });
list1.Add(new Object1 { Prop1 = 4, Prop2 = "2av" });
list1.Add(new Object1 { Prop1 = 5, Prop2 = "2gks" });
list2.Add(new Object2 { Prop1 = 3, Prop2 = "wq" });
list2.Add(new Object2 { Prop1 = 9, Prop2 = "sdf" });
var list = (from l1 in list1
from l2 in list2
select l1).ToList();
Assert.AreEqual(6, list.Count);
}