C# LINQ到SQL:多列上的多个联接。这可能吗?
给定: 名为C# LINQ到SQL:多列上的多个联接。这可能吗?,c#,linq-to-sql,left-join,multiple-columns,C#,Linq To Sql,Left Join,Multiple Columns,给定: 名为table_1的表包含以下列: ID ColumnA ColumnB ColumnC 我有一个SQL查询,其中表_1基于列a,列b,列c自身连接两次。查询可能如下所示: 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.C
table_1
的表包含以下列:
ID
ColumnA
ColumnB
ColumnC
表_1
基于列a
,列b
,列c
自身连接两次。查询可能如下所示:
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 :(
var查询=
从myTABLE1List//列表中的t1开始
在MyTable1列表中加入t2
在t1.ColumnA上等于t2.ColumnA
&&t1.ColumnB等于t2.ColumnA
// ... 在这一点上,intellisense使它变得非常明显
//我做错了什么事:(
如何在LINQ中编写查询?我做错了什么?在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 }
...
var查询=
从myTABLE1List//列表中的t1开始
在MyTable1列表中加入t2
在新的{t1.ColumnA,t1.ColumnB}上等于新的{t2.ColumnA,t2.ColumnB}
...
您必须利用匿名类型,为要比较的多个列组成一个类型
这一点一开始似乎令人困惑,但一旦您熟悉了SQL由表达式组成的方式,它将变得更有意义,在封面下,这将生成您正在寻找的联接类型
编辑添加基于注释的第二次连接示例
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 }
...
var查询=
从myTABLE1List//列表中的t1开始
在MyTable1列表中加入t2
在新的{A=t1.ColumnA,B=t1.ColumnB}上等于新的{A=t2.ColumnA,B=t2.ColumnB}
在MyTable1列表中加入t3
在新的{A=t2.ColumnA,B=t2.ColumnB}上等于新的{A=t3.ColumnA,B=t3.ColumnB}
...
在LINQ2SQL中,使用内部联接时很少需要显式联接
如果您的数据库中有适当的外键关系,您将在LINQ设计器中自动获得一个关系(如果没有,您可以在设计器中手动创建一个关系,尽管您的数据库中确实应该有适当的关系)
然后您可以使用“点符号”访问相关的表
将生成查询
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
在我看来,这更具可读性,可以让您专注于特殊条件,而不是连接的实际机制
编辑当然,这仅适用于您想加入我们的数据库模型的情况。如果您想加入“模型外”,您需要求助于手动加入,如from标题中所述。作者是一个查找两件事一次加入项目结果并继续链接的过程
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别名必须与“equal new”筛选器中e表和t表中的Hrco和位置代码-Hrco和位置代码组合对齐。这将节省您的时间,因为我一直收到“Not in scope on The left side”编译错误,因为我认为该筛选器是筛选器的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>();
从表1e中选择*
加入表2
e、 Hrco=t.Hrco和e.PositionCode=t.PositionCode
注意列与标签A和B的关联。As equal和Bs equal过滤器。
IList list=await(来自_dbContext.table1中的e
在_dbContext.table2中加入t
关于新的{A=e.Hrco,B=e.PositionCode}
等于新的{A=t.Hrco,B=t.PositionCode}
其中e.XMan==员工编号
选择新建MyView
{
雇员=雇员,
LastName=e.LastName,
FirstName=e.FirstName,
Title=t.JobTitle
).ToListAsync();
这对于两个联接非常有效。我需要它来处理三个联接。抱歉,第二个代码块有点误导。如果您在类型推断方面遇到编译器错误,请检查两件事:(1)类型是否相同,以及(2)列名是否相同。名称部分是一个gotcha。即使所有列都是varcharsjoin T2 in db.tbl2 on new{T1.firstName,T1.secondName}等于new{T2.colFirst,T2.colSecond}
,此示例也不会编译。但是,如果将其更改为此,它将编译为join T2 in db.tbl2 on new{N1=T1.firstName,N2=T1.secondName}等于新的{N1=T2.colFirst,N2=T2.colSecond}
命名问题可以通过从myTABLE1List中的T1在新的{colA=T1.ColumnA,colB=T1.ColumnB}上加入myTABLE1List中的T2来解决请允许我编辑该示例,因为它需要分配到匿名属性这里有些东西是错误的..使用LINQ。我可以在多个表上进行连接,我可以在多个字段上进行连接…但是,我不能同时对这两个表进行连接,如示例所示。因此,假设您在1个字段上有一个连接..然后有第二个连接。如果您更改第一个连接join(或两者)只使用new{x.field}等于new{y.field}有一个编译器错误。从功能上讲,您没有更改任何内容。使用.Net 4.6.1。这不一样-问题是关于基于每一列中的多个列连接表,而不是基于每一列中的一个列连接多个表。是的,我看不出这个答案在这里有什么作用。啊哈!!这很有效!关键的区别是,您需要做“ColA=”部分,以便在另一个领域加入相同的领域。多年来我都没有这样做,
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>();