我想知道当用户访问我网站上的表的索引页面并使用搜索功能时,我应该将 where 子句添加到 ienumerable 还是 iqueryable?我知道两者都可以完成,但哪一个更有效,我可以将自定义搜索字符串扩展添加到 iqueryable 吗?
4 回答
将其添加到 IQueryable 会将其添加到进入数据库的查询中,因为它是与数据库的实时连接的一部分。
将其添加到 IEnumerable(不是 IQueryable 类型)将在查询执行后在内存中进行过滤。
如果您正在处理底层的 IQueryable,在这两种情况下,我怀疑会有区别。但是,我建议在 sql profiler 中查看生成的查询,以确保您正在执行预期的查询。
为了以防万一,我会将其添加到您的 IQueryable 中,但由于两者都是接口,因此可能并不重要。如果您的 IEnumerables 始终是 IQueryables,那么您仍然应该获得在数据库上运行查询的好处,而不是在数据库返回结果之后。
IQueryable
并且IEnumerable
是所谓的“接口”。接口定义了实际对象应该能够响应的 API,同时允许实际类型有一定程度的可变性(阅读:对象实现的类)。只要类型实现了接口,一切都可以正常工作,并且您可以(在大多数情况下)将一种类型交换为另一种类型,只要它们都实现相同的接口。
也就是说,IQueryable
实际上是 的扩展IEnumerable
,因此就您在此处讨论的目的而言,它们实际上是同一件事。换句话说,这与从数据库返回的对象集是否转换为 anIQueryable
或 an无关IEnumerable
;在任何一种情况下,查询可能尚未执行,也可能尚未执行,因为两个接口都没有规定必须执行查询。重要的是你是否在代码中做了一些会导致执行查询的事情:比如强制转换为列表 ( .ToList()
) 或迭代结果集 ( for
,foreach
等) 等等。运行计数也会执行查询,但出于稍微不同的原因(您将向数据库发出 COUNT 查询而不是 SELECT)。
寓意是,您只需要注意代码的哪些部分实际上会导致查询被执行,并确保在该点之前发生任何查询更改。
根据您对情况的描述,我会使用 anIQueryable
来运行您Where()
的 's,然后将其转换为 aList<SomeViewModel>
以将其返回到您的页面。这样做将推迟对数据库的查询执行,直到您对其进行细化以返回您需要的内容。
我使用普通的旧变量代替自定义搜索字符串扩展,并根据传入的内容削减我的对象。因此,如果您正在编写一个接收firstName
并lastName
作为参数的搜索控制器,您可以执行以下操作:
IQueryable<User> users = Context.Users;
if (firstName != null)
users = users.Where(x => x.FirstName == firstName);
if(lastName != null)
users = users.Where(x => x.LastName == lastName);
List<SearchResultViewModel> model = users.Select(x => new SearchResultViewModel
{
FirstName = x.FirstName,
LastName = x.LastName,
JobTitle = x.JobTitle
// and so forth for whatever fields you need to return...
}).ToList();
// The ToList() will cause the query to be
// evaluated and executed.
当然,您应该检查以确保您的搜索字段中至少有一个包含某些内容,这样您就不会返回整个表的数据。从这里你可以安装它来接受分页变量,应用排序,各种有趣的东西。