实体框架 - 从ObjectContext查询与从导航属性查询

时间:2011-07-18 10:16:32

标签: linq entity-framework linq-to-entities ienumerable iqueryable

我注意到,根据我从Entity Framework模型中提取数据的方式,我会得到不同类型的结果。例如,获取特定部门的员工列表时:

如果我直接从ObjectContext中提取,我会得到一个IQueryable<Employee>,实际上是System.Data.Objects.ObjectQuery<Employee>

var employees = MyObjectContext.Employees.Where(e => e.DepartmentId == MyDepartment.Id && e.SomeCondtition)

但是如果我使用MyDepartment的导航属性,我会得到一个IEnumerable<Employee>,它实际上是System.Linq.WhereEnumerableIterator<Employee>(System.Linq.Enumerable中的私有类):

var employees = MyDeparment.Employees.Where(e => e.SomeCondtition)

在下面的代码中,我在几个LINQ查询中大量使用employeesWhereOrderByFirstSum等。)< / p>

我应该考虑使用哪种查询方法吗?会有性能差异吗?后者是否使用延迟执行?是一个更好的做法?或者它没有什么区别?

我问这个是因为自从安装ReShaper 6以来,我在使用后一种方法时遇到了很多可能的多次枚举IEnumerable 警告,但在使用直接查询时却没有。我经常使用后一种方法,只是因为它写得更清晰,我想知道这样做是否真的产生了不利影响!

1 个答案:

答案 0 :(得分:2)

有很大的不同。

如果您使用的是第一种方法,则IQueryable = exression树,您仍然可以添加其他表达式,并且只有在执行查询(延迟执行)时,表达式树才会转换为SQL并在数据库。因此,如果您使用第一个示例并添加.Sum某些内容,您将确实在数据库中执行操作,并且它只会将单个数字传回给您的应用程序。这就是linq-to-entities。

第二个示例用于内存收集。导航属性不代表IQueryable(表达式树)。所有linq命令都被视为linq-to-objects =表示导航属性中相关数据的所有记录必须首先从数据库加载到您的应用程序,所有操作都在应用程序服务器的内存中完成。您可以明确地(通过使用Include)或懒惰地加载导航属性(使用Load)(如果启用了延迟加载,则首次访问属性时会自动完成)。因此,如果您想要总结某些内容,则此方案要求您从数据库加载所有数据,然后在本地执行操作。