繁体   English   中英

如何在 LINQ 中对单个连接中的多个字段进行连接

[英]How to do joins in LINQ on multiple fields in single join

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

是我在上面假设 equijoin 时引用的解决方案。

进一步编辑

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

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

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

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

匿名类型的解决方案应该可以正常工作。 LINQ只能代表等值连接(用联接子句,反正),而事实上,你已经什么的说你要根据你的原始查询反正表达。

如果由于某些特定原因您不喜欢匿名类型的版本,您应该解释该原因。

如果你想做一些不同于你最初要求的事情,请举例说明你真正想做的事情。

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

在日期范围内这样做有点困难。 但是,根据“日期范围连接”的确切含义,您可能可以做类似的事情 - 如果您计划创建日期的“带”(例如每年一个),以便在同一年(但不在同一日期)应该匹配,然后您只需使用该乐队作为键就可以做到。 如果它更复杂,例如连接的一侧提供一个范围,连接的另一侧提供单个日期,如果它落在该范围内,则匹配,最好使用where子句处理(在第二个from子句之后) ) 海事组织。 您可以通过订购一侧或另一侧来更有效地找到匹配项来做一些特别时髦的魔术,但这将是一项大量工作 - 我只会在检查性能是否有问题后才做这种事情。

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 }

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

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

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

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

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

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

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

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

你可以做类似(如下)

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......};

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

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

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

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

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

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

 var list= list1.Join(list2,
                       e1 => (e1.val1,e1.val2),
                       e2 => (e2.val1,e2.val2),
                       (e1, e2) => e1).ToList();
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)

这对我有用

声明一个 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM