FirstOrDefault()会导致Linq to SQL进行延迟加载或急切加载。

11

在使用LINQ to SQL时,FirstOrDefault()的默认行为是什么?

例如:

  int value =   (from p in context.tableX         
                select p.Id).FirstOrDefault()      // Value will initialized here or

   if(value > 0)                      // query will be executed here????
   {
    //do something
   }

谢谢


3
仅实体和 IEnumerable 是延迟加载的。 - gdoron
4个回答

12

当使用Linq to SQL和FirstOrDefault()一起使用时,默认行为是什么?

它会急切地计算查询的结果。最简单的方法是意识到返回类型是int,而不是可以推迟到GetEnumerator被调用的IEnumerable<int>,但是int没有这样的机制。

您的问题的措辞表明您是否也在询问是否有一种方法可以更改此行为。有一种方法,但不能直接通过FirstOrDefault或LINQ中的任何机制来实现。但是,您可以使用Lazy<T>来推迟操作。没有编译器,所以如果代码无法编译,请谅解,但它应该非常接近正确。

Lazy<int> value = new Lazy<int>(
    () => {
        var query =
            from p in context.tableX
            select p.Id;
        var result = query.FirstOrDefault();
        return result;
    }
);

if(value.Value > 0) { // execution will be deferred until here
    //
}

1
@Iti Tyagi - 听起来你在问FirstOrDefault()是否会调用GetEnumerator。query.FirstOrDefault()会导致延迟加载还是立即加载(即它会调用GetEnumerator吗)?我相信像query.ToList()这样的语句会强制进行立即加载 - 那么FirstOrDefault()会做同样的事情吗? - Danny Bullis

12

所有标准的Linq运算符,它们返回单个的、不可枚举的结果,在查询被声明的地方立即执行。因此,FirstOrDefaultCountSum以及其他返回单个值的运算符都会立即执行。

下面是一篇很好的MSDN文章《按执行方式分类的标准查询运算符》。


2

急切加载!

如果你仔细想一想,它只是返回一个普通的int - 一个int不可能代表"获取int的方式"。(这就是为什么要使用Lazy<int>的原因...)


2
当您在可枚举结果上使用扩展方法时,它变成了“急切加载”。如果您不使用这些扩展方法,则会变成“延迟加载”,直到您枚举Linq结果之前,实际上无法获取值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接