如果有人能够into在使用LINQ时解释该术语的含义,我将不胜感激.一般来说,我试图了解如何在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;
Run Code Online (Sandbox Code Playgroud)
在阅读了大量文章和观看一些视频之后,我设法让下面的代码得到了解决,但我不觉得我对代码有了完整的了解.令我困惑的是在第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 --"
};
Run Code Online (Sandbox Code Playgroud)
我相信如何:执行左外连接 MSDN 页面的示例部分确实得到了很好的解释。让我们将其投影到您的示例中。引用页面第一段
生成两个集合的左外连接的第一步是使用组连接执行内连接。(有关此过程的说明,请参阅如何:执行内部联接(C# 编程指南)。)在此示例中,Person 对象列表基于与 Pet.Owner 匹配的 Person 对象内联接到 Pet 对象列表。
因此,在您的情况下,第一步是根据对象中的对象匹配来执行对象列表与对象Students列表的内部联接。从引用中可以看出,内部连接是使用group join执行的。如果您查看MSDN 页面中有关如何执行组加入的部分,您可以看到MarksMarkIDStudentsMarkIDMarksNote
无论在第二个集合中是否找到相关元素,第一个集合的每个元素都会出现在组联接的结果集中。在没有找到相关元素的情况下,该元素的相关元素序列为空。因此,结果选择器可以访问第一个集合的每个元素。
在您的示例上下文中,这意味着通过使用into您可以得到group joined所有Students对象以及Marks对象的相关元素序列的结果(如果没有匹配的Marks对象,则该序列将为空)。
现在让我们回到How to: Perform Left Outer Joins MSDN page,特别是第二段
第二步是将第一个(左)集合的每个元素包含在结果集中,即使该元素在右集合中没有匹配项。这是通过对组连接中的每个匹配元素序列调用 DefaultIfEmpty 来完成的。在此示例中,对每个匹配 Pet 对象序列调用 DefaultIfEmpty。如果任何 Person 对象的匹配 Pet 对象序列为空,该方法将返回一个包含单个默认值的集合,从而确保每个 Person 对象都在结果集合中表示。
同样,为了将其投影到您的示例中,DefaultIsEmpty()正在对每个匹配Marks对象序列进行调用。如上所述,如果匹配Marks对象序列对于任何Student对象都是空的,该方法将返回一个包含单个默认值的集合,这确保每个Student对象都将在结果集合中表示。因此,您拥有的是一组元素,其中包含所有Student对象和匹配Marks对象,或者如果没有匹配Marks对象,则默认值为Marks,在本例中为null。