如何在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 }

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

进一步编辑

为了回答批评,我原来的例子是一个等量连接,我承认,我目前的要求是一个等量连接,我已经采用了我上面提到的解决方案。

然而,我正在尝试了解我已经/应该使用LINQ的可能性和最佳实践。我将需要做一个日期范围查询连接与表ID很快,只是先发制人的问题,看起来我必须在where子句中添加日期范围。

一如既往,感谢所有的建议和意见

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

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

您可以这样做(如下所示)

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

使用匿名类型的解决方案应该可以正常工作。LINQ 可以只表示相等连接(无论如何,使用连接子句),事实上,这就是你所说的基于原始查询想要表达的内容。

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

如果你想做一些其他的事情,而不是你最初要求的,请给出一个例子,你真的想做什么。

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

在日期范围内做到这一点有点困难。然而,根据你对“日期范围连接”的确切含义,你可能可以做一些类似的 -如果你计划创建日期的“带”(例如每年一个),这样发生在同一年(但不是在同一日期)的两个条目应该匹配,那么你可以只使用那个带作为键。如果更复杂,例如,连接的一边提供了一个范围,而连接的另一边提供了一个日期,如果它在这个范围内,则匹配,这将更好地用where子句(在第二个from子句之后)IMO来处理。你可以做一些特别时髦的魔术,通过订购一方或另一方来更有效地找到匹配,但这将是大量的工作-我只会在检查性能是否是个问题后做这种事情。

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)

这对我很有用

用一个等价的方法链语法来完成这个:

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

而最后一个参数(x, y) => x是你选择的(在上面的例子中,我们选择x)。

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

如果两个实体中的列名不同,则需要这样做。

如果字段名在实体中不相同

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函数:

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

这也允许通过添加. defaultifempty()轻松地将内连接更改为左连接。

声明一个类(类型)来保存要连接的元素。在下面的例子中,声明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

作为一个完整的方法链,看起来像这样:

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