我真的希望我的标题有点正确,因为我很难用语言表达我的要求,但。。。
我目前正在努力掌握IEnumerables。
我的应用程序中有这样一个类:
public class MyDataRepo : IDisposable
{
private MyEntities context;
public MyDataRepo()
{ context = new MyEntities(); }
public IEnumerable<MyItem> GetMyItems()
{ return context.MyItems.AsEnumerable(); }
public void Dispose()
{ context.Dispose(); }
}
我想我可以这样使用它:
using (MyDataRepo repo = new MyDataRepo())
{
List<int> MyItemIDs = repo.GetMyItems().Where(x => x.ItemName == "Item Name")
.OrderBy(x => x.ItemMajorIssueNumber)
.ThenBy(x => x.ItemMinorIssueNumber)
.Select(x => x.ItemID).ToList();
}
但它比仅仅这样做要慢得多:
using (MyEntities context = new MyEntities())
{
List<int> MyItemIDs = context.MyItems.Where(x => x.ItemName == "Item Name")
.OrderBy(x => x.ItemMajorIssueNumber)
.ThenBy(x => x.ItemMinorIssueNumber)
.Select(x => x.ItemID).ToList();
}
我只是想知道为什么?
根据我的理解,IEnumerable
在调用.ToList()
之前不会对数据库执行任何操作。
在我看来,它们应该是相同的查询,但第二个查询几乎是即时的,因为第一个查询大约需要4-6秒。
我很感激我可能完全误解了IEnumerable
,尽管它很常见。
理想情况下,我宁愿只调用IEnumerable<>
并对其应用过滤器,然后调用.ToList()
来获得我想要的结果,也不必为我需要的针对MyItems的所有查询编写几个方法。
这里我们有IEnumerable<T>
和IQueryable<T>
行为的区别。当你把
List<int> MyItemIDs = repo
.GetMyItems()
.Where(x => x.ItemName == "Item Name")
...
实际上是
List<int> MyItemIDs = context
.MyItems
.AsEnumerable() <- This is the felony!
.Where(x => x.ItemName == "Item Name")
...
您通过.AsEnumerable()
将所有记录(例如,所有1_000_000记录(从RDBMS提取到工作站,然后对其进行筛选(Where
(、排序(OrderBy
(等。
相反,
List<int> MyItemIDs = context
.MyItems
.Where(x => x.ItemName == "Item Name")
...
是IQueryable<T>
直到最后(.ToList()
(,这意味着创建的SQL查询和所有筛选(Where
(、排序(OrderBy
(将在服务器端上执行,而不会出现不需要的提取。