我了解到IQueryable或IEnumerable数据类型不会在第一时间返回结果,只在需要时返回它们。然而,当我在手表检查员中打开那个物体时,我看到所有的物体都在那里。
我的代码中是否有任何错误,或只是因为我在手表上调用它而显示?
[当我在观察对话框中查看 pendings 对象时,我看到了所有列表项,但它不应该在第一个位置加载。我的接近是否有什么问题,或者只是因为我在手表上看到它而显示出来。]
public IQueryable<PurchasePendingView> PurchasePendings() {
var pendings = db.PurchasePendingViews
.Where(m => m.AccountStatusID != StructAccountStatus.Succeed); // when I view it in the watch dialougebox I saw all the list items but it shouldn't load at the first place. Is there anything wrong in my approaching or is it just showing because I had call it on the watch.
if (ApplicationEnvironment.DEBUGGING) {
return pendings;
} else if (IsMobileAccount()) {
var showroom = db.ShowRooms.FirstOrDefault(m=> m.MemberID == employee.MemberID);
if (showroom != null) {
return pendings.Where(m => m.ShowRoomID == showroom.ShowRoomID);
} else {
return pendings.Where(m => m.CountryDivisionID == employee.CountryDivisionID);
}
} else {
//normal salary employee can see every detail
return pendings;
}
}
注意:目前我的延迟加载已关闭。
答案 0 :(得分:5)
首次迭代结果时会对集合进行评估。
由于您在监视检查器中迭代结果,因此它们会被逐渐消除。
答案 1 :(得分:0)
这比解释更容易证明:
public class MeanException : Exception
{
public MeanException() : base() { }
public MeanException(string message) : base(message) { }
}
public static IEnumerable<T> Break<T>(this IEnumerable<T> source)
where T : new()
{
if (source != null)
{
throw new MeanException("Sequence was evaluated");
}
if (source == null)
{
throw new MeanException("Sequence was evaluated");
}
//unreachable
//this will make this an iterator block so that it will have differed execution,
//just like most other LINQ extension methods
yield return new T();
}
public static IEnumerable<int> getQuery()
{
var list = new List<int> { 1, 2, 3, 4, 5 };
var query = list.Select(n => n + 1)
.Break()
.Where(n => n % 2 == 0);
return query;
}
那么,我们在这里有什么。我们有一个自定义异常,所以我们可以独立捕获它。我们有IEnumerable<T>
的扩展方法,一旦评估序列,它将始终抛出异常,但它使用延迟执行,就像Select
和Where
一样。最后,我们有一个获取查询的方法。我们可以在Break
调用之前和之后看到LINQ方法,我们可以看到List
被用作底层数据源。 (在您的示例中,它可以是内存中的某个集合,也可以是查询数据库然后在迭代时迭代结果的对象。)
现在让我们使用这个查询,看看会发生什么:
try
{
Console.WriteLine("Before fetching query");
IEnumerable<int> query = getQuery();
Console.WriteLine("After fetching query");
foreach (var number in query)
{
Console.WriteLine("Inside foreach loop");
}
Console.WriteLine("After foreach loop");
}
catch (MeanException ex)
{
Console.WriteLine("Exception thrown: \n{0}", ex.ToString());
}
如果运行此代码,您将看到的是查询之前的打印(显然)查询后的打印(意味着我们只是从方法返回查询并且从未抛出平均异常)接下来的消息抛出了异常(意味着我们从未进入foreach循环的内部或过去。
这显然是一个用来展示一个概念的人为例子,但实际上你经常会在实践中看到这个。例如,如果在创建数据上下文后丢失了与数据库的连接,则在迭代查询之前,或者如果数据持有者对象已过期且与数据库不匹配,则实际上不会出现异常在同一点会得到一个例外。在一个不太明显的示例中,如果您长时间保持查询,则在获取查询结果时最终会得到数据,而不是在构建查询结果时。这是另一个证明:
var list = new List<int> { 1, 2, 3, 4, 5 };
var query = list.Where(num => num < 5);
Console.WriteLine(query.Count());
list.RemoveAll(num => num < 4);
Console.WriteLine(query.Count()
这里我们有一个数据列表,并计算小于5的项目数(它是4)。然后我们修改列表(根本不改变query
)。我们重新查询query
并最终得到1。