代码之家  ›  专栏  ›  技术社区  ›  johnc

如何在单个联接中的多个字段上执行LINQ联接

  •  219
  • johnc  · 技术社区  · 16 年前

    我需要执行一个linq2dataset查询,该查询在多个字段上执行join(as

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

    我已经找到了一个合适的解决方案(我可以向WHERE子句添加额外的约束,但是这远远不是一个合适的解决方案,或者使用 this 解决方案,但假设为等连接)。

    在LINQ中,可以在一个联接中联接多个字段吗?

    编辑

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

    是我在上面假设的一个等式中引用的解决方案。

    进一步 编辑

    为了回答我最初的例子是equijoin的批评,我承认,我目前的要求是equijoin,我已经采用了我上面提到的解决方案。

    不过,我正在努力了解我在LINQ中有/应该采用哪些可能性和最佳实践。我很快就需要使用表ID进行日期范围查询联接,并且只是抢先解决了这个问题,看起来我必须在WHERE子句中添加日期范围。

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

    12 回复  |  直到 7 年前
        1
  •  81
  •   Jon Skeet    16 年前

    匿名类型的解决方案应该可以正常工作。林克 可以 只表示equijoin(无论如何都有join子句),实际上,这就是您所说的,您无论如何都希望基于原始查询表达的内容。

    如果出于某种特定的原因,您不喜欢匿名类型的版本,那么应该解释这个原因。

    如果你想做你最初要求以外的事情,请举例说明 真的? 想做。

    编辑:回答问题中的编辑:是的,要进行“日期范围”联接,您需要改用WHERE子句。它们在语义上是等价的,所以这只是可用的优化问题。Equijoin通过创建基于内部序列的查找来提供简单的优化(在对象的LINQ中,其中包括LINQ到数据集),将其视为从键到匹配该键的条目序列的哈希表。

    使用日期范围执行此操作有些困难。然而,根据你所说的“日期范围连接”的确切含义,你可能会做些什么 类似的 -如果您计划创建日期的“带区”(例如每年创建一个),使同一年(但不是同一日期)中发生的两个条目匹配,那么您可以只使用该带作为键来创建。如果更复杂,例如连接的一侧提供了一个范围,而连接的另一侧提供了一个单一的日期,如果该日期在该范围内,则最好使用 where 条款(一秒钟后 from 在我看来,你可以通过命令一方或另一方更有效地找到匹配来做一些特别有趣的魔术,但那将是一项很大的工作——我只会在检查性能是否是一个问题之后做这种事情。

        2
  •  114
  •   Nathan W    16 年前
    var result = from x in entity
       join y in entity2 on new { x.field1, x.field2 } equals new { y.field1, y.field2 }
    
        3
  •  64
  •   RealNapster    10 年前
    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
  •  45
  •   niieani    11 年前

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

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

    当最后一个论点 (x, y) => x 是您选择的(在上述情况下,我们选择 x )

        5
  •  27
  •   Alexei - check Codidact    9 年前

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

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

    这还允许通过附加.defaultifempty()轻松地从内部联接更改为左联接。

        6
  •  9
  •   Jhanvi    10 年前
    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
  •  7
  •   tvanfosson    16 年前

    使用join运算符只能执行equijoin。可以使用其他运算符构造其他类型的联接。我不确定使用这些方法或通过更改WHERE子句,您尝试执行的确切联接是否更容易。可以找到有关join子句的文档 here . MSDN有一个 article on join operations 还有到其他连接示例的多个链接。

        8
  •  7
  •   Perpetualcoder    16 年前

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

    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
  •  1
  •   Mahesh    10 年前

    如果实体中的字段名不同

    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
  •  1
  •   Adam Garner    7 年前

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

    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();
    
        11
  •  -1
  •   ChrisF    7 年前

    声明一个类(类型)以保存要联接的元素。在下面的示例中,声明 连接元素

     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
    
        12
  •  -2
  •   user2745564    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)
    

    这对我有用