使用include不会改变行为

有人可以帮我澄清之间的区别:

var query = awlt.People.Include(p => p.EmailAddresses) .Where(p => p.LastName.Equals(lastName)) .SelectMany(a => a.EmailAddresses) .Select(a => a.EmailAddress1); 

  var query = awlt.People .Where(p => p.LastName.Equals(lastName)) .SelectMany(a => a.EmailAddresses) .Select(a => a.EmailAddress1); 

在两种情况下我都得到相同的结果而不知道差异。 Eager Loading是否需要使用Include

这两个查询都是通过使用Eager Loading来检索相关数据(首先通过使用您猜测的Include方法实现Eager加载 ),然后使用默认情况下的延迟加载来检索第二个查询。 但由于Select()SelectMany()操作只会返回EmailAddresses因此Include()方法不会更改行为 。 要查看在您的示例中Include()方法何时成为问题,请阅读以下几行,我将在一个示例中对其进行说明:

要了解这两种加载相关实体之间的差异,当您需要主表的所有检索行的相关数据时, Eager加载通常更有效。 而且当关系不是太多时, 急切加载将是减少服务器上进一步查询的良好做法。 但是当你知道你不会立即需要一个属性时,延迟加载可能是一个不错的选择。 而且,在您的数据库上下文被丢弃并且不再进行延迟加载的情况下,急切加载也是一个不错的选择。 要certificate一个是Lazy Loading,一个是Eager Loading,请考虑以下代码:

 public List GetEmailAddresses() { using (yourEntities awlt = new yourEntities()) { var query = awlt.People .Where(p => p.LastName.Equals(lastName)); return query.ToList(); } } 

调用此方法后,您无法延迟加载相关实体,因为已释放数据库。 要certificate尝试这个:

 var query = GetEmailAddresses(); foreach (var item in query.SelectMany(a => a.EmailAddresses).Select(a => a.EmailAddress1)) { MessageBox.Show(item); } 

你会得到这个错误:

ObjectContext实例已被释放,不能再用于需要连接的操作。

但是,如果您将GetEmailAddresses更改为使用Eager Loading,如下所示:

 public List GetEmailAddresses() { using (yourEntities awlt = new yourEntities()) { var query = awlt.People.Include("EmailAddresses") .Where(p => p.LastName.Equals(lastName)); return query.ToList(); } } 

那么下面的代码应该可以正常工作:

 var query = GetEmailAddresses(); foreach (var item in query.SelectMany(a => a.EmailAddresses).Select(a => a.EmailAddress1)) { MessageBox.Show(item); } 

因此,在处理您的数据库上下文的情况下, Eager Loading将是更好的选择。

不了解EF 7,但在EF 6中,这些语句对数据库产生相同的查询,因此基本相同。 没有任何延迟加载,没有急切的加载(在某种意义上这个术语通常是使用的)。

您需要仅Include实现的实体的属性。 在上面的示例中,您实现了Person.EmailAddresses.EmailAddress1 ,但是您只包含Person.EmailAddresses – 这没有任何效果(有关详细信息,请参见此处 )。

考虑这个示例代码(细节无关紧要,只有带有代码导航属性的Error实体):

 // note we materialized query var errors = ctx.Errors.Include(c => c.Code).ToArray(); // no lazy loading happens here - we already loaded all related Codes with Include var codeIds = errors.Select(c => c.Code.CodeID).ToArray(); 

还有这个:

 // no need to include here! var codeIds = ctx.Errors.Select(c =>c.Code.CodeID).ToArray(); 

并包括:

 // include has no effect here! var codeIds = ctx.Errors.Inlcude(c => c.Code).Select(c => c.Code.CodeID).ToArray(); 

什么是渴望加载? 当您使用Include语句将其他数据包含到相关实体时。 这里Include语句没有效果,它只是什么都没做,所以我们不能说出那个急切的加载。

什么是延迟加载? 当你第一次访问导航属性时加载它。 您不在示例中执行此操作,因此也没有延迟加载。

这两个示例只是对数据库执行相同的查询(在使用枚举`ToArray`等实现它们之后)。

两个查询的结果完全相同(也是关于’eager’和’lazy’加载)。
在这种情况下,我认为查询也非常相似或相同,但从不信任EF Provider生成的查询。 要查看生成的查询,可以使用断点停止程序,并查看查询对象(将鼠标指向它)。 这是EF Provider生成的查询。

关于Eager加载(Include语句)在这种情况下它应该没用,因为它用于加载输出对象的属性。 在这种情况下,您选择EMailAddress1,因此使用Include可以急切加载EMailAddress1的属性(并避免在EMailAddress1访问期间进行延迟查询)。

如果在运行查询后查看SQL Server Profiler,可以找到差异。 因此,在您的第一种情况下,只有一个查询进入您的数据库并从People表和EmailAddresses表中获取记录,而在第二种情况下,它对数据库执行两次查询并首先获取People,然后在第二个查询中获取EmailAddresses。 因此,第一种情况称为急切加载,第二种情况称为延迟加载。