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
,然后像本地数据一样进行枚举
这在一定程度上取决于提供者是谁,但也有一些是这样的