LINQtoSQL: 在多个列上进行多重连接。这可能吗?

给出:

一个名为 TABLE_1的表,其中包含以下列:

  • ID
  • ColumnA
  • ColumnB
  • ColumnC

我有 SQL 查询,其中 TABLE_1连接本身两次基于 ColumnAColumnBColumnC。查询可能类似于下面这样:

Select t1.ID, t2.ID, t3.ID
From TABLE_1 t1
Left Join TABLE_1 t2 On
t1.ColumnA = t2.ColumnA
And t1.ColumnB = t2.ColumnB
And t1.ColumnC = t2.ColumnC
Left Join TABLE_1 t3 On
t2.ColumnA = t3.ColumnA
And t2.ColumnB = t3.ColumnB
And t2.ColumnC = t3.ColumnC
... and query continues on etc.

问题:

我需要在 LINQ 中重写这个查询。我已经尝试过了:

var query =
from t1 in myTABLE1List // List<TABLE_1>
join t2 in myTABLE1List
on t1.ColumnA equals t2.ColumnA
&& t1.ColumnB equals t2.ColumnA
// ... and at this point intellisense is making it very obvious
// I am doing something wrong :(

我如何在 LINQ 中写我的查询? 我做错了什么?

256018 次浏览

在 Linq 将多列连接到 SQL 有点不同。

var query =
from t1 in myTABLE1List // List<TABLE_1>
join t2 in myTABLE1List
on new { t1.ColumnA, t1.ColumnB } equals new { t2.ColumnA, t2.ColumnB }
...

您必须利用匿名类型,并为希望比较的多个列创建一个类型。

一开始,这似乎有些令人困惑,但是一旦您熟悉了 SQL 是如何由表达式组成的,那么它就会变得更有意义,在这种掩盖之下,它将生成您正在寻找的连接类型。

EDIT 添加基于注释的第二个连接示例。

var query =
from t1 in myTABLE1List // List<TABLE_1>
join t2 in myTABLE1List
on new { A = t1.ColumnA, B = t1.ColumnB } equals new { A = t2.ColumnA, B = t2.ColumnB }
join t3 in myTABLE1List
on new { A = t2.ColumnA, B =  t2.ColumnB } equals new { A = t3.ColumnA, B = t3.ColumnB }
...

在 LINQ2SQL 中,使用内部连接时很少需要显式连接。

如果您在数据库中有适当的外键关系,那么您将在 LINQ 设计器中自动获得一个关系(如果没有,那么您可以在设计器中手动创建一个关系,尽管您的数据库中应该有适当的关系)

parent-child relation

然后你可以用“点符号”访问相关的表

var q = from child in context.Childs
where child.Parent.col2 == 4
select new
{
childCol1 = child.col1,
parentCol1 = child.Parent.col1,
};

将生成查询

SELECT [t0].[col1] AS [childCol1], [t1].[col1] AS [parentCol1]
FROM [dbo].[Child] AS [t0]
INNER JOIN [dbo].[Parent] AS [t1] ON ([t1].[col1] = [t0].[col1]) AND ([t1].[col2] = [t0].[col2])
WHERE [t1].[col2] = @p0
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [4]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1

在我看来,这是更具可读性,让您专注于您的特殊情况,而不是连接的实际机制。

剪辑
当然,这只适用于您想要加入到我们的数据库模型行中的情况。如果你想加入“模型之外”,你需要求助于手动加入,就像在 回答中一样,来自 Quintin Robinson

Title _ Authors 是一个查找项目结果一次连接两个事物并继续链接

        DataClasses1DataContext db = new DataClasses1DataContext();
var queryresults = from a in db.Authors
join ba in db.Title_Authors
on a.Au_ID equals ba.Au_ID into idAuthor
from c in idAuthor
join t in db.Titles
on c.ISBN equals t.ISBN
select new { Author = a.Author1,Title= t.Title1 };


foreach (var item in queryresults)
{
MessageBox.Show(item.Author);
MessageBox.Show(item.Title);
return;
}

你也可以使用:

var query =
from t1 in myTABLE1List
join t2 in myTABLE1List
on new { ColA=t1.ColumnA, ColB=t1.ColumnB } equals new { ColA=t2.ColumnA, ColB=t2.ColumnB }
join t3 in myTABLE1List
on new {ColC=t2.ColumnA, ColD=t2.ColumnB } equals new { ColC=t3.ColumnA, ColD=t3.ColumnB }

我想给出另一个使用多个(3)连接的例子。

 DataClasses1DataContext ctx = new DataClasses1DataContext();


var Owners = ctx.OwnerMasters;
var Category = ctx.CategoryMasters;
var Status = ctx.StatusMasters;
var Tasks = ctx.TaskMasters;


var xyz = from t in Tasks
join c in Category
on t.TaskCategory equals c.CategoryID
join s in Status
on t.TaskStatus equals s.StatusID
join o in Owners
on t.TaskOwner equals o.OwnerID
select new
{
t.TaskID,
t.TaskShortDescription,
c.CategoryName,
s.StatusName,
o.OwnerName
};

如果两个表中的列数不相同,还可以联接,并且可以将静态值映射到表列

from t1 in Table1
join t2 in Table2
on new {X = t1.Column1, Y = 0 } on new {X = t2.Column1, Y = t2.Column2 }
select new {t1, t2}

A 和 b 别名必须与 e 表和 t 表中的 Hrco 和位置代码对齐-Hrco 和位置代码组合在“等于新”过滤器中。这将节省您的时间,因为我不断得到“不在作用域左侧”编译错误,因为我认为过滤器是 e. Hrco,t. Hrco 配对的过滤器。

select * from table1 e
join table2 t on
e.Hrco=t.Hrco and e.PositionCode=t.PositionCode


Notice the association of the columns to the labels A and B. The As equal and the Bs equal filter.


IList<MyView> list = await (from e in _dbContext.table1
join t in _dbContext.table2
on new { A= e.Hrco, B= e.PositionCode }
equals new {A= t.Hrco,B=t.PositionCode }
where e.XMan == employeeNumber


select new MyView
{
                                                                        

Employee=e.Employee,
LastName=e.LastName,
FirstName=e.FirstName,
Title=t.JobTitle
).ToListAsync<MyView>();

您可以使用 LINQ 方法语法来连接多个列,

var query = mTABLE_1.Join( // mTABLE_1 is a List<TABLE_1>
mTABLE_1,
t1 => new
{
ColA = t1.ColumnA,
ColB = t1.ColumnB,
ColC = t1.ColumnC
},
t2 => new
{
ColA = t2.ColumnA,
ColB = t2.ColumnB,
ColC = t2.ColumnC
},
(t1, t2) => new { t1, t2 }).Join(
mTABLE_1,
t1t2 => new
{
ColA = t1t2.t2.ColumnA,
ColB = t1t2.t2.ColumnB,
ColC = t1t2.t2.ColumnC
},
t3 => new
{
ColA = t3.ColumnA,
ColB = t3.ColumnB,
ColC = t3.ColumnC
},
(t1t2, t3) => new
{
t1 = t1t2.t1,
t2 = t1t2.t2,
t3 = t3
});

注意: 编译器在编译时将查询语法转换为方法语法。