我需要执行一个 LINQ2DataSet 查询,该查询对多个字段进行连接(如
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 }
是我在上面假设等值连接时引用的解决方案。
进一步编辑
为了回答关于我的原始示例是等值连接的批评,我承认,我目前的要求是等值连接,并且我已经采用了上面提到的解决方案。
但是,我正在尝试了解我拥有/应该使用 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 }
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 }
如果两个实体中的列名不同,则需要执行此操作。
OR
而不是 AND
!我应该怎么办? new {...} equals new {....}
会起作用吗?
匿名类型的解决方案应该可以正常工作。 LINQ 只能表示等值连接(无论如何都带有连接子句),实际上这就是您所说的,无论如何您都希望根据原始查询来表达。
如果您出于某种特定原因不喜欢匿名类型的版本,则应说明该原因。
如果您想做的不是您最初要求的事情,请举例说明您真正想做的事情。
编辑:回应问题中的编辑:是的,要进行“日期范围”连接,您需要改用 where 子句。它们在语义上实际上是等价的,所以这只是可用优化的问题。 Equijoins 通过创建基于内部序列的查找来提供简单的优化(在 LINQ to Objects 中,其中包括 LINQ to DataSets) - 将其视为从键到与该键匹配的条目序列的哈希表。
使用日期范围执行此操作有些困难。但是,根据您所说的“日期范围加入”的确切含义,您可能能够做一些类似的事情 - 如果您计划创建日期“带”(例如每年一个),例如同一年(但不在同一日期)出现的两个条目应该匹配,那么您只需使用该带作为键即可。如果它更复杂,例如连接的一侧提供一个范围,而连接的另一侧提供一个日期,如果它在该范围内匹配,则使用 where
子句会更好地处理(在一秒钟后from
子句)IMO。您可以通过订购一侧或另一侧来更有效地找到匹配项来做一些特别时髦的魔术,但这将是很多工作 - 我只会在检查性能是否有问题后才会做那种事情。
只需使用等效的方法链语法完成此操作:
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() 轻松地从内连接更改为左连接。
{ ... } equals new { ... }
语法相同的性能。 LinqPad 是查看表达式行为方式的绝佳工具(如果使用 LINQ2SQL,则使用 SQL 脚本、表达式树等)
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......};
使用连接运算符,您只能执行等值连接。可以使用其他运算符构造其他类型的连接。我不确定您尝试使用这些方法或更改 where 子句是否更容易进行确切的连接。可以在 here 中找到有关 join 子句的文档。 MSDN 也有一个 article on join operations,其中包含指向其他连接示例的多个链接。
如果实体中的字段名称不同
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});
作为一个完整的方法链,如下所示:
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
不定期副业成功案例分享
on new { X1= x.field1, X2= x.field2 } equals new { X1=y.field1, X2= y.field2 }
后它起作用了X1
的数据类型应该在两边相同。在我的例子中,第一个表中的X1
数据类型是Nullable Integer
,而在连接表中是Non-nullable integer
。然后我不得不将 Nullable 转换为不可为空的 Integer 以使其工作