283

我需要执行一个 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 }

是我在上面假设等值连接时引用的解决方案。

进一步编辑

为了回答关于我的原始示例是等值连接的批评,我承认,我目前的要求是等值连接,并且我已经采用了上面提到的解决方案。

但是,我正在尝试了解我拥有/应该使用 LINQ 的可能性和最佳实践。我很快将需要使用表 ID 进行日期范围查询连接,并且只是先发制人,看起来我必须在 where 子句中添加日期范围。

一如既往地感谢您提供的所有建议和意见

4

13 回答 13

156
var result = from x in entity
   join y in entity2 on new { x.field1, x.field2 } equals new { y.field1, y.field2 }
于 2008-12-17T03:11:02.780 回答
100
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 }

如果两个实体中的列名不同,则需要执行此操作。

于 2014-10-13T22:01:55.920 回答
94

匿名类型的解决方案应该可以正常工作。LINQ只能表示等值连接(无论如何都带有连接子句),实际上这就是您所说的,无论如何您都希望根据原始查询来表达。

如果您出于某种特定原因不喜欢匿名类型的版本,则应说明该原因。

如果您想做的不是您最初要求的事情,请举例说明您真正想做的事情。

编辑:回应问题中的编辑:是的,要进行“日期范围”连接,您需要改用 where 子句。它们在语义上实际上是等价的,所以这只是可用优化的问题。Equijoins 通过创建基于内部序列的查找来提供简单的优化(在 LINQ to Objects 中,其中包括 LINQ to DataSets) - 将其视为从键到与该键匹配的条目序列的哈希表。

使用日期范围执行此操作有些困难。但是,根据您所说的“日期范围连接”的确切含义,您可能可以做类似的事情- 如果您计划创建日期的“带”(例如每年一个),以便两个条目出现在同一年(但不是同一天)应该匹配,那么您只需使用该带作为键即可。如果它更复杂,例如连接的一侧提供一个范围,而连接的另一侧提供一个日期,如果它在该范围内匹配,则最好使用where子句处理(在一秒钟后from条款)IMO。您可以通过订购一侧或另一侧来更有效地找到匹配项来做一些特别时髦的魔法,但这将是很多工作 - 我只会在检查性能是否存在问题后才会做那种事情。

于 2008-12-17T06:32:32.360 回答
58

只需使用等效的方法链语法完成此操作:

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

而最后一个参数(x, y) => x是您选择的(在上述情况下,我们选择x)。

于 2014-03-04T15:53:04.407 回答
38

我认为一个更具可读性和灵活性的选择是使用 Where 函数:

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

这也允许通过附加 .DefaultIfEmpty() 轻松地从内连接更改为左连接。

于 2015-12-09T10:30:34.857 回答
13
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
              };
于 2014-08-22T05:08:16.793 回答
9

你可以做类似(下)的事情

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......};
于 2008-12-17T06:01:14.293 回答
7

使用连接运算符,您只能执行等值连接。可以使用其他运算符构造其他类型的连接。我不确定您尝试使用这些方法或更改 where 子句是否更容易进行确切的连接。可以在此处找到有关 join 子句的文档。MSDN 有一篇关于连接操作的文章,其中包含指向其他连接示例的多个链接。

于 2008-12-17T03:58:41.280 回答
7

如果实体中的字段名称不同

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});
于 2014-12-02T02:56:08.690 回答
3

作为一个完整的方法链,如下所示:

lista.SelectMany(a => listb.Where(xi => b.Id == a.Id && b.Total != a.Total),
                (a, b) => new ResultItem
                {
                    Id = a.Id,
                    ATotal = a.Total,
                    BTotal = b.Total
                }).ToList();
于 2018-04-16T09:41:58.067 回答
2

我使用元组来做到这一点,这是两列的示例:

 var list= list1.Join(list2,
                       e1 => (e1.val1,e1.val2),
                       e2 => (e2.val1,e2.val2),
                       (e1, e2) => e1).ToList();
于 2020-08-28T13:40:51.100 回答
-2
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)

这对我有用

于 2013-09-12T02:13:51.153 回答
-3

声明一个 Class(Type) 来保存你想要加入的元素。在下面的示例中声明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
于 2017-09-01T19:22:29.103 回答