2014-11-21 78 views
7

如果有人能够在使用LINQ时解释术语into的含义,我将不胜感激。一般来说,我想了解如何制作INNER JOINLEFT OUTER JOINC#使用LINQ进行左外连接 - 了解代码

我有主表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

请参见:http://stackoverflow.com/a/3855926/468973 – Magnus 2014-11-21 10:26:18

+0

请坚持每一个岗位的问题。这两个问题解决了与EF合作的完全不同的方面。对于第一个问题,看到这一点:http://stackoverflow.com/a/15599143/861716 – 2014-11-21 10:27:03

+0

有关内部连接和左外一些信息加入我建议https://www.youtube.com/watch?v=Te2o5qakvZk HTTPS ://www.youtube.com/watch?v = 5K8jwrlKV8E – 2014-11-21 10:31:29

回答

4

我相信从How to: Perform Left Outer Joins MSDN page实例部分是真的很好地解释。让我们把它投影到你的例子。从页面

两个集合的生产左外的第一步加入引述第一段是 执行由使用一组连接的内连接。 (请参见如何:执行 内部联接(C#编程指南)以获取有关此 进程的说明。)在此示例中,Person对象列表是内部联合的 到基于匹配的Person对象的Pet对象列表 Pet.Owner。

所以你的情况,第一步是进行Students对象列表的内联同Marks对象的基础上MarkID列表中Students对象Marks对象匹配MarkID。从报价中可以看出,内连接正在使用group join执行。如果您检查Note部分MSDN页面上如何执行组加入,你可以看到,无论

第一集合中的每个元素出现在结果集中 组的加入是否相关元素的发现 第二集。 在这种情况下,其中没有相关元素被找到, 的该元素相关的元素的序列是空。因此, 结果选择器可以访问第一个 集合的每个元素。

这意味着在你的榜样的背景是什么,是通过使用into你有group joined结果,你都Students对象,Marks对象的相关元素的顺序(如果没有匹配的Marks对象,该序列将是空的)。

现在,让我们回到How to: Perform Left Outer Joins MSDN page,特别是第二段

第二步是包括第一(左) 集合中的结果,即使设定的每一个元素,如果该元素在 不匹配正确的收藏。这是通过对来自组联接的每个匹配元素序列调用DefaultIfEmpty 来完成的。在该示例 ,DefaultIfEmpty被称为匹配宠物 的每一目标序列。该方法返回包含一个单一的, 默认值,如果匹配宠物对象的序列是空的任何 Person对象,从而确保每个Person对象被表示的结果集合中 集合。

再次,项目到您的示例,DefaultIsEmpty()被称为匹配Marks的每一目标序列。如上所解释的,该方法返回包含一个单一的,缺省值,如果匹配Marks对象的序列为空任何Student对象,从而确保每个Student对象将所得集合中表示的集合。因此,您拥有的是一组元素,其中包含所有Student对象,并匹配Marks对象,或者如果没有匹配的对象Marks,则默认值为Marks,在本例中为null

+0

行。我觉得我有一个非常接近的地方。我已经理解了所有,直到(并且包括)'into'。它按“学生”分组结果。但是,让我们说,我可以为每个学生有不止一个标记。我相信我有一个分组连接的结构化结果如下:'Student1和来自连接的其他字段:Student1'的5个标记列表,'Student2 ...:null','Student3 ...:2个标记列表'等等。这是如何投影到一个简单的SQL数据库表中的,每个'StudentX'的所有可能的'Marks'都有重复记录'StudentX'? – Celdor 2014-11-21 12:20:44

+0

对不起,但我不确定我了解你的问题。你想知道这个ef查询会产生什么sql查询吗?此外,您是否检查[分组连接]的示例(http://msdn.microsoft.com/zh-cn/library/bb397905.aspx),该示例包含大小写,左集合中的1个元素具有多个关联元素从正确的收集,可能与您的问题有关。 – Michael 2014-11-21 12:39:07

+0

对不起,我的英语不是第一语言! – Celdor 2014-11-21 13:30:50

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”

+0

错了。您只是将外部联接转换为内部联接。 – 2014-11-21 10:46:27

+0

@Ziko,虽然你接受了这个答案,但请注意这个查询可能会产生不同于你的结果的结果。 – 2014-11-21 10:52:44

+0

对不起,你是对的,我没有足够的意识到纯粹的SQL代码 – Markus 2014-11-24 17:24:59