División de datos en múltiples tablas de tamaño fijo

Tengo una tabla de datos que tiene 1123 registros. Quiero dividir esta tabla en 5 tablas de datos separadas de tamaño fijo. El límite de tamaño para cada tabla es 225.

Por lo tanto, el tamaño de los datos resultantes será:

DT1 : 225 rows DT2 : 225 rows DT3 : 225 rows DT4 : 225 rows DT5 : 223 rows (remaining rows) 

Pude encontrar cómo dividir datos en función del valor de la columna usando LINQ aquí .

También encontré una manera de dividir datos en varias tablas aquí . Quería saber si hay una mejor manera de hacer esto. Código de publicación desde el enlace:

 private static List SplitTable(DataTable originalTable, int batchSize) { List tables = new List(); 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; } 

Necesita ayuda en la división de datos en tamaño fijo.

Una vez hice este pequeño método de extensión :

 public static IEnumerable> ToChunks(this IEnumerable 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; } } 

eso corta cualquier IEnumerable en trozos del tamaño de trozo especificado.

Teniendo esto, simplemente puedes hacer:

 var tables = originalTable.AsEnumerable().ToChunks(225) .Select(rows => rows.CopyToDataTable()) 

La razón por la que esto podría funcionar mejor que un simple foreach es esa lista. list.GetRange es un método muy eficiente para obtener un rango de filas de una lista. Tengo curiosidad por saber qué vas a encontrar.

 private static List SplitTable(DataTable originalTable, int batchSize) { List tables = new List(); 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; } 

Otra forma de hacerlo para gente perezosa 🙂

 private static DataTable GetDataTable(IEnumerable 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; } 

Y el cliente lo llamará así:

  `var nthDataTable = GetDataTable(model, skip: n, take: m);` 

Las soluciones proporcionadas aquí no funcionaron para mí, si el último conjunto de registros es menor que el tamaño deseado de la parte de datos, entonces simplemente ignorará esos registros y resultará en perderlos … por ejemplo, si hay 5 registros y el tamaño de la tabla de fragmentos. es 2, entonces creará solo 2 datos que pueden ignorar el último registro.

Aquí está el código corregido que me funcionó en todos los escenarios.

Los usuarios que trabajan en VB.NET pueden o no pueden usar LINQ muchas veces, por lo que si necesita el código vb.net del mismo, haga clic aquí Dividir grandes datos en trozos en c # y vb.net

  private static List SplitTable(DataTable mainTable, int batchSize) { List tables = new List(); 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; }