我开始使用存储库模式进行数据访问,使用实体框架和LINQ作为非测试存储库实现的基础。当调用返回 N 条记录而不是 List<T> 时,我看到的大多数示例都返回 AsQueryable()。这样做有什么好处?
5 回答
AsQueryable 只是创建一个查询,获取列表所需的指令。您可以稍后对查询进行进一步更改,例如添加新的 Where 子句,这些子句会一直发送到数据库级别。
AsList 返回一个包含内存中所有项目的实际列表。如果您向其中添加新的 Where cluse,您将无法获得数据库提供的快速过滤。相反,您获取列表中的所有信息,然后过滤掉应用程序中不需要的信息。
所以基本上它归结为等到最后一刻才做出承诺。
返回IQueryable<T>
的好处是,在您真正开始枚举结果之前执行会延迟,并且您可以将查询与其他查询组合在一起,并且仍然可以在服务器端执行。
问题是您无法在此方法中控制数据库上下文的生命周期 - 您需要一个开放的上下文,并且必须确保它保持打开状态,直到查询被执行。然后你必须确保上下文将被释放。List<T>
如果您以、或类似的形式返回结果T[]
,您将失去组合查询的延迟执行和服务器端执行,但您可以控制数据库上下文的生命周期。
当然,什么最适合,取决于实际要求。这是另一个没有单一真理的问题。
AsQueryable
是一种扩展方法,IEnumerable<T>
它可以做两件事:
- 如果
IEnumerable<T>
工具IQueryable<T>
只是强制转换,什么也不做。 - 否则会创建一个“假”
IEnumerable<T>
(EnumerableQuery<T>
)来实现编译 lambdas 并调用 Enumerable 扩展方法的每个方法。
因此,在大多数情况下,使用 AsQueryable 是没有用的,除非你被迫将 IQueryable 传递给一个方法,而你有一个 IEnumerable,否则这是一个 hack。
注意: AsQueryable 是一个 hack,IQueryable 当然不是!
返回IQueryable<T>
将推迟查询的执行,直到它的结果被实际使用。在此之前,您还可以对 ; 执行额外的数据库查询操作IQueryable<T>
。在List
你被限制在通常效率较低的内存操作中。
IQueryable
:这是一种延迟执行 - 延迟加载,因此您的查询被评估并命中数据库。如果我们添加任何附加子句,它将使用带有过滤器的所需查询命中 Db。IEnumerable
:是急切加载,因此记录将首先加载到内存中操作,然后执行操作。
因此,取决于用例,例如在对大量记录进行分页时,我们应该使用IQueryable<T>
,如果操作时间短且不会创建大量内存存储使用IEnumerable
。