3

我注意到,根据我如何从我的实体框架模型中提取数据,我得到了不同类型的结果。例如,在一个特定的部门,让员工名单时:实体框架 - 从ObjectContext查询与从导航中查询属性

如果我直接从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) 

在下面的代码,我大量使用employees在几个LINQ查询(WhereOrderByFirstSum等)

我应该考虑到我使用的查询方法?会有性能差异吗?后者是否使用延期执行?是一个更好的做法?或者它没有影响?

我用后一种方法但是使用直接查询时没有问这个,因为自从安装整形6,我收到了大量的IEnumerable警告可能多个枚举。我一直在更频繁地使用后一种方法,只是因为它写得更干净,而且我想知道这样做实际上是否具有不利影响!

回答

2

有很大的区别。

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

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

+0

谢谢你。在这种情况下,我应该完全避免导航属性,还是等同于确保我在可枚举导航属性上调用CreateSourceQuery()? – Ross

+0

一旦你使用'CreateSourceQuery'你再次使用IQueryable这是OK。导航属性本身不用于查询。他们用于处理相关对象。 –

+0

导航属性是否比遵守查询进行过滤有什么优势? – ManirajSS