SqlDataAdapter::Fill 是获取整个结果集还是按需获取?

Does SqlDataAdapter::Fill fetch the whole result set or is it on-demand?

我试图将 DataGridView 连接到 SQL 服务器, 中概述的解决方案使用了 SqlDataAdapter 和 DataTable:

var adapter = new SqlDataAdapter("select * from foo", "server=myhost-pc\sqlexpress;trusted_connection=yes;database=test1");
var table = new DataTable();
adapter.Fill(table);
view.DataSource = table;

我想知道这个方法是否从服务器获取整个数据集,或者它是否将 DataGridView 连接到服务器以便它可以按需获取新行。

例如,如果 table 有 100 万行,是否会在 SqlDataAdapter::Fill 返回之前将所有行提取并写入 DataTable 对象?

是的,它将创建对象并在您的网格视图上实现以显示您的所有数据,问题是您如何编写 SQL 查询,您可以使用一些 SQL 关键字,如 TOP、LIMIT、OFFSET。

限制通过 SQL 加载的行数,要么在质量上(WHERE...)限制它们,要么通过一个相当生硬的 LIMIT 子句限制它们。您还可以使用 DataAdapter 加载 "pages" 或组中的行 - 一次一点。这使用 MySQL 但它适用于 DBProviders 的许多其他(全部?):

int pageSize = 10000;
int page = 0;
...

初始加载:

string SQL = "SELECT * FROM Sample";

using (MySqlConnection dbCon = new MySqlConnection(MySQLConnStr))
{
    dtSample = new DataTable();

    daSample = new MySqlDataAdapter(SQL, dbCon);          
    daSample.FillSchema(dtSample, SchemaType.Source);
    dbCon.Open();

    int Rows = daSample.Fill((page*pageSize), pageSize, dtSample);
}

dgv2.DataSource = dtSample;
this.lblPages.Text = String.Format("Rows {0} - {1}",
                         ((page * pageSize) + 1),
                         (page + 1 * pageSize));
page += 1;

关键是 DataAdapter(int, int, DataTable) 重载:它允许您指定要加载的第一行和行数。我不会为每个页面重新创建 DataAdapter,而是使用 form/class 一级。阅读下一页会给您一些选择:

dgv2.SuspendLayout();
dtSample.Rows.Clear();
int Rows = daSample.Fill((page * pageSize), pageSize, dtSample);
dgv2.ResumeLayout();

this.lblPages.Text = String.Format("Rows {0} - {1}",
                         ((page * pageSize) + 1),
                         (page + 1 * pageSize));

if (Rows != pageSize)    // last page?
    page = 0;           
else
    page += 1;

如果您清除行,DataTable会累积它们:也就是说,在加载第二组后,它将具有页面的所有行1 和 2。

让它们累积起来很有用,这样任何给定的集合都只加载一次。如果一次只显示一页仍然很重要,您可以使用 DataView 仅显示当前组: