【发布时间】:2018-01-24 06:59:49
【问题描述】:
我有一个包含 900 万到 1300 万条记录的文件。由于列表有大小限制,我已将代码分成 100 万条记录的块并尝试插入记录。
这里是读取和分块文件的代码:
public static void InsertBulkData(string file)
{
List<FileData> lstFileData = new List<FileData>();
using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (StreamReader sr = new StreamReader(bs))
{
string line = string.Empty;
while ((line = sr.ReadLine()) != null)
{
FileData obj = new FileData();
obj.Property1= line.Substring(5, 9).Trim();
obj.Property2= line.Substring(19, 40).Trim();
lstFileData.Add(obj);
if (lstFileData.Count == 1000000)
{
InsertDataIntoDatabase(lstFileData);
lstFileData = null;
GC.Collect();
lstFileData = new List<FileData>();
}
}
}
}
}
}
现在我们进入循环 9 次。但是当我谈到保存数据时,它只保存第一次。休息 8 次就会抛出异常。
private static void InsertDataIntoDatabase(List<FileData> lstFileData)
{
String query = @"INSERT INTO table
(
PrimaryCol,
Column1,
Column2
)
VALUES
(
primaryCol.NEXTVAL,
:Property1,
:Property2,
)";
using (OracleConnection Conn = new OracleConnection())
{
try
{
Conn.ConnectionString = ConfigurationManager.ConnectionStrings["connection"].ToString();
Conn.Open();
using (var command = Conn.CreateCommand())
{
command.CommandText = query;
command.CommandType = CommandType.Text;
command.BindByName = true;
// In order to use ArrayBinding, the ArrayBindCount property
// of OracleCommand object must be set to the number of records to be inserted
command.ArrayBindCount = lstFileData.Count;
command.Parameters.Add(":Property1", OracleDbType.Varchar2, lstFileData.Select(c => c.Property1).ToArray(), ParameterDirection.Input);
command.Parameters.Add(":Property2", OracleDbType.Varchar2, lstFileData.Select(c => c.Property2).ToArray(), ParameterDirection.Input);
command.ExecuteNonQuery();
Conn.Close();
}
}
catch (Exception ex)
{
Conn.Close();
Console.WriteLine("Exception is:" + ex.InnerException);
}
}
}
所以在第一次迭代后,我们在 command.ExecuteNonQuery() 中遇到错误。谁能说出原因以及可能的解决方案是什么?
【问题讨论】:
-
有什么异常?
-
系统内存不足异常
-
我认为在 InsertBulkData 方法中创建 lstFileData 时使用大内存在每个步骤的末尾清空您的列表,而不是 om new
-
第一次插入但下次它会抛出错误。如果我们创建 2M 的块并将其全部插入,我们就有 1M 的块,它会插入,但如果我们尝试在循环中插入,则会抛出错误。
-
已经这样做了。如果你看到我已经将它分配给 null 并且还收集了调用垃圾收集器的空间。
标签: c# oracle bulkinsert