gpt4 book ai didi

c# - 如何从表中逐 block 获取数据?

转载 作者:行者123 更新时间:2023-11-29 06:06:30 24 4
gpt4 key购买 nike

我正在尝试从 MySQL 表中逐 block 获取数据。

我有如下表格:

HistoryLogs = 10986119

现在我想从 MyQSL 中逐 block 获取数据并将其传递给 sqlbulk 副本进行处理。我已将批量大小确定为 1000

例如,如果我有 10000 条记录,那么我的查询将如下所示:

SELECT * FROM tbl LIMIT 0,1000;
SELECT * FROM tbl LIMIT 1000,2000;
SELECT * FROM tbl LIMIT 2000,3000;
SELECT * FROM tbl LIMIT 9000,10000;

所以首先我将从表中获取总记录,然后尝试如下所示:

 private int FetchCount(string table)
{
using (MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM " + table, conn))
{
cmd.CommandTimeout = 0;
return cmd.ExecuteNonQuery();
}
}

string query = string.Empty;
string table ="HistoryLogs";
int records = FetchCount(table);
for (int i = 0; i < records / 1000 ; i++) //
{
here I would like to create chunk by chunk query and pass it to Process method
}


private MySqlDataReader Process(MySqlConnection conn, string query)
{
using (MySqlCommand cmd = new MySqlCommand(query, conn))
{
cmd.CommandTimeout = 0;
MySqlDataReader reader = cmd.ExecuteReader();
return reader;
}
}

所以我不知道如何创建分页查询,也不确定我的想法是否正确。

最佳答案

有点不确定您想使用什么技术从数据库中获取数据。

由于 Linq 关键字,我假设您需要一个 Linq 语句,它为您提供具有给定 pageSize 的项目页面。

然而,您不确定如何获取第 X 页的数据。您是否有一个 IQueryable 记录要分成几页(如在 Entity Framework 中 - 强烈推荐),或者您想更改您的SQL 语句,以便它给你第 X 页?

IQueryable 方法

假设您需要类型 T 的记录页并且您有一个 IQueryable<T>获取类型 T 的所有记录。

 IQueryable<T> allRecords = ...;

您想将这个序列分成几页。每个页面都有一个 PageSize , 一个 PageNr和一系列记录:

class Page<T>
{
public int PageSize {get; set;}
public int PageNr {get; set;}
public IEnumerable<T> Contents {get; set;}
}

现在要将 AllRecords 分成一系列页面,我使用扩展方法:

public static class PagingExtensions
{
public static IQueryable<Page<T>> ToPages<T>(this IQueryable<T> allRecords, int pageSize)
{
return allRecords.Select( (record, i) => new
{
PageNr = i / pageSize,
Record = record,
})
.GroupBy(item => item.PageNr)
// intermediate result: sequence of IGrouping<int, T>
// where key is pageNr
// and each element in the group are the records for this page
.Select(group => new Page<T>
{
PageNr = group.Key,
PageSize = pageSize,
Contents = (IEnumerable<T>) group
});
}
}

将 MyRecords 序列分成页面的代码将是:

const int pageSize = 1000;
IQueryable<MyRecord> allMyRecords = ...
IQueryable<Page<MyRecord>> pages = allMyRecords.ToPages(1000);

// do what you want with the pages, for example:
foreach (Page<MyRecord> page in pages)
{
Console.WriteLine($"Page {page.PageNr}");
foreach (MyRecord record in Page.Contents)
{
Console.WriteLine(record.ToString());
}
}

请注意,所有使用的函数都使用延迟执行。在您枚举它们之前,不会获取记录。

如果您希望能够在本地内存而不是数据库中的页面中划分集合,请使用 IEnumerable<T>而不是 IQueryable<T> .

没有 IQueryable 的方法

如果您没有 IQueryable 来获取所有记录,您要么必须自己创建一个实现它的类,要么根据要获取的页面调整您的 SQL 查询。不过,我不推荐第一种方法。

class Page<T>
{
public Page(SqlConnection conn, int pageNr, int pageSize)
{
this.PageNr = pageNr;
this.PageSize = pageSize;
}
private readonly SqlConnection conn;
public int PageSize {get; private set;}
public int PageNr {get; private set;}

public IEnumerable<T> ReadContents()
{
int offset = this.PageNr * this.PageSize;
int fetch = this.PageSize;
string cmdText = "SELECT col1, col2, ..."
+ " FROM ... "
+ " WHERE ... "
+ " ORDER BY -- "
// this is a MUST there must be ORDER BY statement
//-- the paging comes here
+ $" OFFSET {offset} ROWS"
+ $" FETCH NEXT {fetch} ROWS ONLY;";

using (SqlCommand cmd = new SqlCommand("cmdText, conn))
{
using (var sqlDataReader = cmd.ExecuteQuery())
{
List<T> readItems = sqlDataReader...;
// you know better than I how to use the SqlDataReader
return readItems
}
}
}
}

Fetch/Offset 而不是 Enumerable Skip/Take 的想法来自 Implement paging in SQL在 stackoverflow 上。

关于c# - 如何从表中逐 block 获取数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41237439/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com