如果有人在使用 LINQ 时可以解释术语into
的含义,我将不胜感激。一般来说,我试图了解如何在 C#中进行 INNER JOIN , LEFT OUTER JOIN 等。
我有一个主表Students
,它存储了一些外键ID,然后在运行查询时用它们的名字替换它们。这些名称是从Marks
,SoftwareVersions
,Departments
等查找表中读取的。所有字段都是必填字段MarkID
。我尝试在 LINQ 中构建的查询是:
SELECT * FROM dbo.Students
INNER JOIN dbo.Departments ON dbo.Students.DepartmentID=dbo.Departments.DepartmentID
INNER JOIN dbo.SoftwareVersions ON dbo.Students.SoftwareVersionID=dbo.SoftwareVersions.SoftwareVersionID
INNER JOIN dbo.Statuses ON dbo.Students.StatusID=dbo.Statuses.StatusID
LEFT JOIN dbo.Marks ON dbo.Students.MarkID=dbo.Marks.MarkID
WHERE dbo.Students.DepartmentID=17;
在阅读了大量文章并观看了一些视频之后,我设法让下面的代码得到了解决,但我不觉得我对代码有完整的理解。令我困惑的是第5行以into
结尾,然后是以from m ...
开头的下一行。我很困惑into
做了什么,以及from m ...
中发生了什么。这是LINQ中的代码:
var result = from st in dbContext.Students where st.DepartmentID == 17
join d in dbContext.Departments on st.DepartmentID equals d.DepartmentID
join sv in dbContext.SoftwareVersions on st.SoftwareVersionID equals sv.SoftwareVersionID
join stat in dbContext.Statuses on st.StatusID equals stat.StatusID
join m in dbContext.Marks on st.MarkID equals m.MarkID into marksGroup
from m in marksGroup.DefaultIfEmpty()
select new
{
student = st.StudentName,
department = p.DepartmentName,
software = sv.SoftwareVersionName,
status = st.StatusName,
marked = m != null ? m.MarkName : "-- Not marked --"
};
答案 0 :(得分:4)
我相信来自How to: Perform Left Outer Joins MSDN page的示例部分已得到很好的解释。让我们把它投射到你的例子中。引用页面第一段
生成两个集合的左外连接的第一步是 使用组连接执行内部联接。 (参见如何:执行 内部连接(C#编程指南)对此进行了解释 process。)在此示例中,Person对象列表是内部连接的 到基于匹配的Person对象的Pet对象列表 Pet.Owner。
因此,在您的情况下,第一步是根据Students
对象中Marks
的{{1}}对象列表,执行MarkID
个对象列表的内部联接匹配Students
对象中的MarkID
。从引用中可以看出,内部联接正在使用group join执行。如果您在MSDN页面中查看有关如何执行群组加入的Marks
部分,则可以看到
第一个集合的每个元素都出现在a的结果集中 无论是否在相关元素中找到,都可以进行组连接 第二集。 如果找不到相关元素, 该元素的相关元素序列为空 。该 因此,结果选择器可以访问第一个元素 采集。
在您的示例的上下文中,这意味着使用Note
您有into
个结果,其中包含所有group joined
个对象,以及{{1的相关元素序列对象(如果没有匹配的Students
对象,则序列将为空)。
现在让我们回到Marks
,特别是第二段
第二步是包括第一个(左)的每个元素 结果集中的集合,即使该元素没有匹配项 正确的收藏。这是通过调用DefaultIfEmpty来完成的 来自组连接的每个匹配元素序列。在这 例如,在匹配Pet的每个序列上调用DefaultIfEmpty 对象。该方法返回一个包含单个的集合, 如果匹配Pet对象的序列对于任何对象为空,则为默认值 Person对象,从而确保表示每个Person对象 在结果集合中。
同样,要将此项目投射到您的示例中,将在匹配的Marks
个对象的每个序列上调用How to: Perform Left Outer Joins MSDN page
。如上所述,如果匹配DefaultIsEmpty()
对象的序列对于任何Marks
对象为空,则该方法返回包含单个默认值的集合,这将确保每个Marks
对象将被表示在最终的集合中。因此,您拥有的元素集包含所有Student
个对象和匹配的Student
对象,或者如果没有匹配的Student
对象,则默认值为{{1} },在本例中为Marks
。
答案 1 :(得分:1)
我能说的是"进入MarksGroup"将连接表的结果数据存储到临时(基于应用程序,而不是基于数据库)结果集中(以sql术语表示:表格,因此其为SELECT INTO
)
在下一行中,您的代码会从Marksgroup中选择包含您数据的列(以sql术语:SELECT student, department, software, status, marked FROM Marksgroup
所以基本上,它从数据库中获取数据,然后将其放在" Marksgroup中,并在下一步中让Marksgroup回到您的手中以取出您想要使用的数据在你的c#代码中。
尝试摆脱Marksgroup,它应该是可能的(没有经过测试的代码)。它应该是这样的:
from st in dbContext.Students where st.DepartmentID == 17
join d in dbContext.Departments on st.DepartmentID equals d.DepartmentID
join sv in dbContext.SoftwareVersions on st.SoftwareVersionID equals sv.SoftwareVersionID
join stat in dbContext.Statuses on st.StatusID equals stat.StatusID
join m in dbContext.Marks on st.MarkID equals m.MarkID
select new
{
student = st.StudentName,
department = p.DepartmentName,
software = sv.SoftwareVersionName,
status = st.StatusName,
marked = m != null ? m.MarkName : "-- Not marked --"
};
你的第二个问题是' m' :如果没有临时结果集,这也应该显示不同的行为" Marksgroup"