C# 在Linq和Exe时间中使用ToList()

C# 在Linq和Exe时间中使用ToList(),c#,asp.net,linq,C#,Asp.net,Linq,下面是我课本上的一个例子: var allGenres = from genre in myEntities.Genres.Include("Reviews") orderby genre.Name select new { genre.Name, genre.Reviews }; Repeater1.DataSource = allGenres.ToList(); Repeater1.DataBind(); 书上说: 只要调用T

下面是我课本上的一个例子:

var allGenres = from genre in myEntities.Genres.Include("Reviews")
                orderby genre.Name
                select new { genre.Name, genre.Reviews };
Repeater1.DataSource = allGenres.ToList();
Repeater1.DataBind();
书上说:

只要调用ToList(),就会执行查询,并从数据库中检索相关的类型和评论,并将其分配给DataSource属性


所以我的问题是,如果我去掉
Repeater1.DataSource=allGenres.ToList(),var allGenres包含什么?由于查询尚未执行?

如果您使用的是实体框架,则allGeneres将是
IQueryable
接口的实例。这种行为称为延迟执行。如需更多参考

如果您使用的是实体框架,则allGeneres将是
IQueryable
接口的一个实例。这种行为称为延迟执行。有关更多参考资料,请参见三个阶段

  • 首先,当创建查询时
  • 其次,当查询变量被迭代时(延迟执行)
  • 第三,强制查询即时结果

    var allGenres=来自myenties.Genres.Include(“评论”)中的流派
    orderbygenre.Name
    选择新{genre.Name,genre.Reviews}

  • 在此代码中,仅创建查询。它就像一个人死在墓地里一样。 如果需要延迟执行,那么可以使用for循环等对结果进行迭代

    要强制立即执行,可以使用转换运算符,如

    ToList, ToArray, ToLookup, and ToDictionary. 
    
    希望能有帮助

    您可以在此行上放置断点:

    var allGenres = from genre in myEntities.Genres.Include("Reviews")
                orderby genre.Name
                select new { genre.Name, genre.Reviews };
    
    注意什么也没发生。在下一行之后,voila SQL Profiler将显示正在发生的SQL查询:

    Repeater1.DataSource = allGenres.ToList();
    

    有三个阶段需要理解

  • 首先,当创建查询时
  • 其次,当查询变量被迭代时(延迟执行)
  • 第三,强制查询即时结果

    var allGenres=来自myenties.Genres.Include(“评论”)中的流派
    orderbygenre.Name
    选择新{genre.Name,genre.Reviews}

  • 在此代码中,仅创建查询。它就像一个人死在墓地里一样。 如果需要延迟执行,那么可以使用for循环等对结果进行迭代

    要强制立即执行,可以使用转换运算符,如

    ToList, ToArray, ToLookup, and ToDictionary. 
    
    希望能有帮助

    您可以在此行上放置断点:

    var allGenres = from genre in myEntities.Genres.Include("Reviews")
                orderby genre.Name
                select new { genre.Name, genre.Reviews };
    
    注意什么也没发生。在下一行之后,voila SQL Profiler将显示正在发生的SQL查询:

    Repeater1.DataSource = allGenres.ToList();
    

    您的对象
    allGenres
    是一个实现
    IQueryable
    的对象。这意味着它代表一个序列,它有函数来获取序列的第一个元素,一旦得到了元素,就可以获取下一个元素,直到没有更多的元素

    部分定义了序列中的元素类型。因此,
    IQueryable
    表示您可以查询一系列的
    书籍
    ,您可以逐一列举这些书籍。序列的每个元素都是类
    Book

    此枚举是使用IQueryable的基本接口提供的,即
    IEnumerable

    在最低级别,此枚举按如下方式进行:

    IEnumerable<Book> books = ... // for example new List<Book>(), or new Book[10]
    IEnumerator<Book> bookEnumerator = books.Getenumerator();
    
    // as long as there are books, print the title:
    // the first MoveNext() moves to the first element
    // every other MoveNext() move to the next element
    // it returns false if there is no such element (no first, or no next)
    while (bookEnumerator.MoveNext())
    {
        // the enumerator points to the next element. Property Current contains this element
        Book book = bookEnumerator.Current;
        Console.WriteLine(book.Title);
    }
    
    foreach
    将为您执行
    GetEnumerator()
    /
    MoveNext()
    /
    Current

    请注意,
    IEnumerable
    并不表示枚举本身,它表示枚举的能力。很多时候,人们并不那么精确,把IEnumerable称为序列本身。但请记住:要访问序列中的元素,您需要对它们进行枚举(使用MoveNext或调用foreach)

    IQueryable
    似乎与
    IEnumerable
    非常相似。不同之处在于,它通常意味着由不同的进程处理,如数据库管理系统或不同计算机上的服务器,它还可以表示CSV文件中的行,或其他任何内容。IQueryable的目的是将数据的获取方式与获取数据的操作分开

    就像IEnumerable具有枚举的能力一样,IQueryable也具有查询数据的能力

    为此,
    IQueryable
    有一个
    表达式
    和一个
    提供程序
    表达式
    以通用方式定义必须获取的数据。
    提供者
    知道必须提供数据(数据库),以及该数据提供者需要什么语言(SQL)

    也许您已经注意到有两种LINQ语句。返回IQueryable的和不返回IQueryable的。第一组是函数,如
    Where
    Select
    Join
    GroupBy
    。它们都会返回某种类型的IQueryable

    只要连接此组的函数,表达式就会更改。查询尚未执行。返回值仍然是表示查询能力的对象。这些函数使用延迟执行(或延迟执行),这意味着查询尚未执行。您可以识别这些函数,因为它们返回
    IQueryable
    。这些函数描述的备注部分还提到执行被延迟

    只有在调用
    GetEnumerator()
    /
    MoveNext()
    之后,才直接或间接使用
    foreach
    执行查询

    如果开始枚举,
    表达式
    将发送给
    提供者
    ,后者将
    表达式
    翻译成查询执行者理解的语言(SQL),并命令执行者执行查询。提取的数据被转换为
    IEnumerable
    ,然后像本地数据一样进行枚举

    这在一定程度上取决于提供者是谁,但也有一些是这样的