Как выполнять объединения в LINQ для нескольких полей в одном соединении

Мне нужно выполнить запрос LINQ2DataSet, который делает соединение более чем в одном поле (как

var result = from x in entity
join y in entity2 
       on x.field1 = y.field1 
and 
          x.field2 = y.field2

Я нашел подходящее решение (я могу добавить дополнительные ограничения в предложение where, но это далеко не подходящее решение или использовать это решение, но это предполагает эквити).

Возможно ли, чтобы LINQ присоединился к нескольким полям в одном соединении?

ИЗМЕНИТЬ

var result = from x in entity
             join y in entity2
             on new { x.field1, x.field2 } equals new { y.field1, y.field2 }

- это решение, на которое я ссылался, считая, что это выше.

Далее EDIT

Чтобы ответить на критику, что мой оригинальный пример был equijoin, я подтверждаю, что мое текущее требование для equijoin, и я уже использовал решение, на которое я ссылался выше.

Я, однако, пытаюсь понять, какие возможности и лучшие практики у меня есть/должны использовать с LINQ. Мне скоро понадобится соединение запроса диапазона дат с идентификатором таблицы, и он просто упредил эту проблему. Похоже, мне придется добавить диапазон дат в предложение where.

Спасибо, как всегда, за все высказанные предложения и комментарии

Ответ 1

Решение с анонимным типом должно работать нормально. LINQ может представлять только equijoins (с предложениями join, в любом случае), и действительно, то, что вы сказали, что хотите выразить в любом случае на основе вашего исходного запроса.

Если вам не нравится версия с анонимным типом по какой-то определенной причине, вы должны объяснить эту причину.

Если вы хотите сделать что-то другое, кроме того, что вы изначально попросили, пожалуйста, дайте пример того, что вы действительно хотите сделать.

EDIT: ответ на редактирование в вопросе: да, чтобы присоединиться к "диапазону дат", вам нужно вместо этого использовать предложение where. На самом деле они семантически эквивалентны, так что это просто вопрос доступных оптимизаций. Equijoins обеспечивают простую оптимизацию (в LINQ to Objects, которая включает LINQ to DataSets), создавая поиск, основанный на внутренней последовательности, - думайте об этом как хэш-таблицу от ключа к последовательности записей, соответствующих этому ключу.

Выполнение этого с диапазонами дат несколько сложнее. Однако, в зависимости от того, что вы подразумеваете под "соединением диапазона дат", вы можете сделать что-то подобное - если вы планируете создавать "полосы" дат (например, один раз в год), так что две записи, которые происходят в в том же году (но не в ту же дату) должен совпадать, тогда вы можете сделать это, просто используя эту группу в качестве ключа. Если это более сложно, например. одна сторона соединения предоставляет диапазон, а другая сторона соединения предоставляет единственную дату, соответствующую, если она попадает в этот диапазон, которая лучше обрабатывается с помощью предложения where (после второго предложения from). IMO, Вы могли бы придумать какую-то особенную волшебную магию, заказав одну или другую сторону, чтобы найти совпадения более эффективно, но это было бы большой работой - я бы сделал это только после проверки того, является ли производительность проблемой.

Ответ 2

var result = from x in entity
   join y in entity2 on new { x.field1, x.field2 } equals new { y.field1, y.field2 }

Ответ 3

var result = from x in entity1
             join y in entity2
             on new { X1= x.field1, X2= x.field2 } equals new { X1=y.field1, X2= y.field2 }

Вам нужно сделать это, если имена столбцов различаются в двух объектах.

Ответ 4

Просто, чтобы завершить это с помощью синтаксиса схемы эквивалентного метода:

entity.Join(entity2, x => new {x.Field1, x.Field2},
                     y => new {y.Field1, y.Field2}, (x, y) => x);

В то время как последний аргумент (x, y) => x - это то, что вы выбрали (в приведенном выше случае мы выбираем x).

Ответ 5

Я думаю, что более читаемым и гибким вариантом является использование функции Where:

var result = from x in entity1
             from y in entity2
                 .Where(y => y.field1 == x.field1 && y.field2 == x.field2)

Это также позволяет легко перейти от внутреннего объединения к левому соединению, добавив .DefaultIfEmpty().

Ответ 6

var result = from x in entity
             join y in entity2
             on new { X1= x.field1, X2= x.field2 } equals new { X1=y.field1, X2= y.field2 }
             select new 
             {
               /// Columns
              };

Ответ 7

Используя оператор объединения, вы можете выполнять только equijoins. Другие типы объединений могут быть построены с использованием других операторов. Я не уверен, будет ли точное соединение, которое вы пытаетесь сделать, будет проще с помощью этих методов или путем изменения предложения where. Документацию по предложению join можно найти здесь здесь. MSDN имеет статью об операциях объединения с несколькими ссылками на примеры других объединений.

Ответ 8

вы можете сделать что-то вроде (ниже)

var query = from p in context.T1

        join q in context.T2

        on

        new { p.Col1, p.Col2 }

        equals

         new { q.Col1, q.Col2 }

        select new {p...., q......};

Ответ 9

Если имя поля отличается от сущностей

var result = from x in entity
   join y in entity2 on 
          new {
                field1=   x.field1,
               field2 =  x.field2 
             } 
          equals
         new { 
                field1= y.field1,
                field2=  y.myfield
              }
select new {x,y});

Ответ 10

Объявите класс (Тип), чтобы удерживать элементы, которые хотите присоединиться. В приведенном ниже примере объявите JoinElement

 public class **JoinElement**
{
    public int? Id { get; set; }
    public string Name { get; set; }

}

results = from course in courseQueryable.AsQueryable()
                  join agency in agencyQueryable.AsQueryable()
                   on new **JoinElement**() { Id = course.CourseAgencyId, Name = course.CourseDeveloper } 
                   equals new **JoinElement**() { Id = agency.CourseAgencyId, Name = "D" } into temp1

Ответ 11

from d in db.CourseDispatches
                             join du in db.DispatchUsers on d.id equals du.dispatch_id
                             join u in db.Users on du.user_id equals u.id
                             join fr in db.Forumreports on (d.course_id + '_' + du.user_id)  equals  (fr.course_id + '_'+ fr.uid)

это работает для меня