場景:百萬行文本文件(自定義分隔符)導入數據庫,需根據目標表結構動態構建 `DataTable` 並進行強類型轉換。
private static readonly Dictionary DbTypeToClr = new()
{
{"VARCHAR2", typeof(string)}, {"NVARCHAR2", typeof(string)},
{"NUMBER", typeof(decimal)}, {"INT", typeof(int)},
{"DATE", typeof(DateTime)}, {"TIMESTAMP", typeof(DateTime)},
{"CLOB", typeof(string)}, {"BLOB", typeof(byte[])}
};
private static object ConvertValue(string raw, Type targetType)
{
if (string.IsNullOrEmpty(raw)) return DBNull.Value;
try
{
if (targetType == typeof(DateTime))
return DateTime.ParseExact(raw, new[] {"yyyy-MM-dd", "yyyy/MM/dd HH:mm:ss"}, null);
return Convert.ChangeType(raw, targetType);
}
catch { return DBNull.Value; } // 或拋出異常記錄壞行
}
public async Task ImportLargeFile(string filePath, string tableName, string splitChar, int batchSize = 5000)
{
var dt = BuildTargetDataTable(tableName); // 根據元數據構建空 DataTable
using var reader = new StreamReader(filePath, Encoding.Default);
string line;
int count = 0;
while ((line = await reader.ReadLineAsync()) != null)
{
var fields = line.Split(new[] { splitChar }, StringSplitOptions.None);
var row = dt.NewRow();
for (int i = 0; i < Math.Min(fields.Length, dt.Columns.Count); i++)
row[i] = ConvertValue(fields[i], dt.Columns[i].DataType);
dt.Rows.Add(row);
if (++count % batchSize == 0)
{
await BulkInsertAsync(dt); // SqlBulkCopy / OracleBulkCopy
dt.Clear(); // 釋放內存
}
}
if (dt.Rows.Count > 0) await BulkInsertAsync(dt);
}