我有一个包含1123条记录的数据表。我想将此表拆分为5个固定大小的单独数据表。每个表的大小限制为225。
因此产生的数据表的大小将为:
DT1 : 225 rows
DT2 : 225 rows
DT3 : 225 rows
DT4 : 225 rows
DT5 : 223 rows (remaining rows)
我能够找到如何使用LINQ here基于列值拆分数据表。
我还找到了一种将数据表拆分为多个表here的方法。想知道是否有更好的方法来做到这一点。从链接发布代码:
private static List<DataTable> SplitTable(DataTable originalTable, int batchSize)
{
List<DataTable> tables = new List<DataTable>();
int i = 0;
int j = 1;
DataTable newDt = originalTable.Clone();
newDt.TableName = "Table_" + j;
newDt.Clear();
foreach (DataRow row in originalTable.Rows)
{
DataRow newRow = newDt.NewRow();
newRow.ItemArray = row.ItemArray;
newDt.Rows.Add(newRow);
i++;
if (i == batchSize)
{
tables.Add(newDt);
j++;
newDt = originalTable.Clone();
newDt.TableName = "Table_" + j;
newDt.Clear();
i = 0;
}
}
return tables;
}
需要帮助将数据表拆分为固定大小。
答案 0 :(得分:12)
我曾经做过这个小extension method:
public static IEnumerable<IEnumerable<T>> ToChunks<T>(this IEnumerable<T> enumerable,
int chunkSize)
{
int itemsReturned = 0;
var list = enumerable.ToList(); // Prevent multiple execution of IEnumerable.
int count = list.Count;
while (itemsReturned < count)
{
int currentChunkSize = Math.Min(chunkSize, count - itemsReturned);
yield return list.GetRange(itemsReturned, currentChunkSize);
itemsReturned += currentChunkSize;
}
}
将任何IEnumerable
切割成指定块大小的块。
有了这个,你可以简单地做:
var tables = originalTable.AsEnumerable().ToChunks(225)
.Select(rows => rows.CopyToDataTable())
这可能比简单foreach
表现更好的原因是list.GetRange
是从列表中获取一系列行的非常有效的方法。我很想知道你会发现什么。
答案 1 :(得分:1)
private static List<DataTable> SplitTable(DataTable originalTable, int batchSize)
{
List<DataTable> tables = new List<DataTable>();
int i = 0;
int j = 1;
DataTable newDt = originalTable.Clone();
newDt.TableName = "Table_" + j;
newDt.Clear();
foreach (DataRow row in originalTable.Rows)
{
DataRow newRow = newDt.NewRow();
newRow.ItemArray = row.ItemArray;
newDt.Rows.Add(newRow);
i++;
if (i == batchSize)
{
tables.Add(newDt);
j++;
newDt = originalTable.Clone();
newDt.TableName = "Table_" + j;
newDt.Clear();
i = 0;
}
}
if (newDt.Rows.Count > 0)
{
tables.Add(newDt);
j++;
newDt = originalTable.Clone();
newDt.TableName = "Table_" + j;
newDt.Clear();
}
return tables;
}
foreach (var dt1 in SplitTable(table1, 2))
{
DataTable dt = dt1;
}
答案 2 :(得分:0)
为懒惰的人做的另一种方式:)
private static DataTable GetDataTable<T>(IEnumerable<T> data, int skip, int take)
{
var properties = TypeDescriptor.GetProperties(typeof(T));
var dataTable = new DataTable();
foreach (PropertyDescriptor prop in properties)
dataTable
.Columns
.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType)
?? prop.PropertyType);
foreach (var item in data.Skip(skip).Take(take))
{
var row = dataTable.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
dataTable.Rows.Add(row);
}
return dataTable;
}
客户会这样称呼它:
var nthDataTable = GetDataTable(model, skip: n, take: m);
答案 3 :(得分:-1)
这里给出的解决方案对我不起作用,如果最后一组记录小于所需的块数据表大小那么它将简单地忽略那些记录并导致丢失它们...如果有5条记录并且块表大小为2,那么它将只创建2个数据表而忽略最后一条记录。
以下是在所有情况下都适合我的更正代码。
使用VB.NET的用户可能会或可能无法多次使用LINQ,因此如果您需要相同的vb.net代码,请查看Split large datatable into chunks in c# and vb.net
private static List<DataTable> SplitTable(DataTable mainTable, int batchSize)
{
List<DataTable> tables = new List<DataTable>();
int i = 0;
int j = 1;
int rowCount = 0;
DataTable tempDt = mainTable.Clone();
tempDt.TableName = "ChunkDataTable" + j.ToString();
tempDt.Clear();
foreach (DataRow row in mainTable.Rows) {
rowCount += 1;
DataRow newRow = tempDt.NewRow();
newRow.ItemArray = row.ItemArray;
tempDt.Rows.Add(newRow);
i += 1;
if (i == batchSize | rowCount == mainTable.Rows.Count) {
tables.Add(tempDt);
j += 1;
tempDt = mainTable.Clone();
tempDt.TableName = "ChunkDataTable" + j.ToString();
tempDt.Clear();
i = 0;
}
}
return tables;
}