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);

    }
Другие вопросы по тегам