我在理解IQueryable 时遇到了问题

所以我想了解IQueryable 。 我正在阅读的教程建议使用它但不确定为什么。 代码只是使用LINQ to SQL返回一些值。 我过去已经做了很多次,但没有使用IQueryable

为什么在我的函数中使用它返回超过1的值?

这是我的代码:

 public IQueryable GetItems() { return from item in db.Items where item.IsActive == true orderby item.ItemNumber select item; } 

IQueryable将查询表示为表达式树,而不在服务器上对其进行评估。 这允许您在实际生成SQL之前指定进一步的处理。

在上面的例子中,这意味着您可以使用调用GetItems()的结果执行操作,并将原始查询和额外内容作为单个查询发送:

 var recentItems = from item in GetItems() where item.Timestamp > somedate select item; foreach (var item in recentItems) { // Do something with an active recent item. } 

在我们尝试在foreach循环中使用结果之前,没有任何内容发送到服务器。 此时,LINQ-to-SQL提供程序评估整个表达式,包括GetItems()内生成的位和之后指定的位,并发出单个SQL语句,选择所有活动和最近的项。

为了阐明技术性, IQueryable是一个IEnumerable ,当您尝试在其上调用GetEnumerator()方法时,它的提供程序会计算最终的SQL。 您可以通过调用它来显式地执行此操作,也可以通过在foreach语句中使用它来隐式执行此操作。 此外,像ToArray()这样的扩展方法将在内部执行其中一个,从而产生相同的效果。

IQueryable(在枚举之前)不是结果,而是用于返回结果的逻辑。

要使用LINQ2SQL示例…假设您返回了一个IQueryable客户端。 在不会是客户列表的引擎盖下(直到你ToList()它),但实际上将是一个SQL查询,如下所示:

 SELECT * FROM [Clients] 

现在这很方便,因为我们还没有打到数据库! 因此,假设当IQueriable返回时,我们希望将其优化为名为“Bob”的客户端,我们可以这样做:

 var clients = GetClients().Where(c => c.Name == "Bob"); 

现在,IQueriable看起来像这样:

 SELECT * FROM [Clients] WHERE Name = 'Bob'. 

现在,当我执行clients.ToList()时,该查询将运行,数据库被命中,我有一个名为bob的客户端列表,而无需选择所有客户端然后在内存中浏览它们,或执行2个单独的数据库命中。

有一个例子,当你的datacontext退出范围时,你会在后面尝试并获取子元素(例如:在using语句中运行你的select)。 这是LINQ2SQL中负载选项派上用场的地方。

希望有所帮助