3

我想知道 LINQ 和 SqlDataProvider 设法遍历整个表。

对于下面的示例,

  • 整个 foo 项是否已一次性加载到内存中,CLR 是否遍历内存中的 foo 项?

  • 或者 foo 项目是从 SQL Server 分块加载的?

  • 或者它们一次只能从 SQL SERVER 加载到 MEMORT 一个 foo 中?

  • 或者 ?

 

using (var context = new FooEntities())
{
    var allItems = from foo in context.Foos
                   select foo;      

    // Are all foos LOADED into the MEMORY at once?
    // Or they come from SQL SERVER in chunks?
    foreach (f in foos)
        Console.WriteLine(f.ID);
}
4

3 回答 3

2

这取决于 ORM 工具。目前还不清楚,但它看起来FooEntities实体框架?

首先,请注意,大多数“完整”的 ORM 将(默认情况下)将它加载的所有对象附加到身份管理器/更改管理器中,这意味着一旦看到对象,它们将在 ORM 实例的生命周期内一直存在(尽管有时有禁用此功能的方法)。

其次,请注意,通常类似的结果.Foos将是一个“实体集”或类似的,一个完全加载的数据集;但同样,它不一定

基本上,这取决于很多不在问题中的细节。但是,通常有 API 可以加载非缓冲(假脱机)的数据,并且不附加到更改管理器/身份管理器。例如,LINQ-to-SQL 具有ObjectTrackingEnabled和其他一些切换功能。

如果您只是在使用可以延迟处理数据、将行具体化为对象的工具,那么dapper可能会很有用:

foreach(EntityType row in connection.Query<EntityType>(
   "select * from TableName", buffered: false))
{
    // fully streaming, no identity manager
    Console.WriteLine(row.Id);
    // ...etc
}
于 2012-10-22T12:56:44.747 回答
0

在您的具体示例中,您很可能会将整个表格拉入内存。对 DB 的调用将在 开始时进行foreach,看起来像SELECT * FROM FOO. 尝试像其他人建议的那样跨过并观看分析器。

SQL Server 探查器非常适合这些东西,EFProfiler 也是如此。请参阅此处: EFProfiler 网站上的http://www.hibernatingrhinos.com/products/efprof/learn,了解使用 Linq 的一些“反模式”。这些实际上几乎适用于任何类型的数据访问。还请查看 Joe Albahari 的 LINQ 测验:http ://www.albahari.com/nutshell/linqquiz.aspx也有一些有趣的东西需要注意 LINQ。

于 2012-10-22T13:22:38.870 回答
0

是的,只要开始访问它。这些被加载到内存中。

只有virtual对象的属性不会被加载。

如果您不想一次加载所有对象,则可以使用TakeandSkip进行分页。

// Take only 100 objects.
var someitems = allItems.Skip(100).Take(100);

为了更好地理解,请查看文章。

Linq to SQL 延迟加载 - 延迟加载

于 2012-10-22T12:50:17.773 回答