[英]SQL connection closes during SqlBulkCopy
我正在嘗試使用SqlBulkCopy將數據導入到臨時表中。
private bool CreateTempTable(IDbConnection conn, byte[] fileByteArray, string tempTableName)
{
try
{
Stream stream = new MemoryStream(fileByteArray);
using (var reader = new CsvReader(stream, false, System.Text.Encoding.UTF8))
{
// Bulk insert the data into a temporary table.
using (SqlBulkCopy bulkCopy = new SqlBulkCopy((SqlConnection)conn))
{
// Import the data into the temp table
bulkCopy.DestinationTableName = tempTableName;
bulkCopy.EnableStreaming = true;
bulkCopy.BatchSize = 20000;
bulkCopy.BulkCopyTimeout = 600;
bulkCopy.WriteToServer(reader);
}
}
}
catch (Exception ex)
{
Logger.Error(ex, $"CreateTempTable(): Exception while creating the TempTable \"{tempTableName}\" - {ex.Message}");
return false;
}
return true;
}
在另一個異步運行的方法中調用此方法。 連接是通過類似於以下代碼的代碼傳遞和維護的:
private async Task<bool> ConsumeAsyn(byte[] fileByteArray, string tempTableName)
{
using (var conn = (SqlConnection)OpenConnection())
{
if (CreateTempTable(conn, fileByteArray, tempTableName))
{
// success
}
else
{
// fail
}
}
}
基本上,這就是ConsumeAsync的調用方式:
public async Task<bool> ProcessNextAsync2()
{
try
{
isIdle = false;
string filePath = ImportFilePickupPath + "\\" + Filename;
byte[] inStream = await LoadImportFileAsync(filePath);
bool consumeSuccess = await Consume(inStream, "##TempTable");
if (consumeSuccess)
{
// Delete the file
DeleteImportFile(filePath);
}
else
{
// Rescedule job
}
isIdle = true;
}
catch (Exception ex)
{
isIdle = true;
}
return isIdle;
}
如果我在csv中使用大約100行的小型記錄集,則一切正常。 問題是如果我有成千上萬的記錄,則在批量導入過程中連接將終止。
如何將連接傳遞給方法,並確保在批量導入完成之前它保持打開狀態?
也許是一個答案,也許不是,但是可能需要將IDisposables(至少/尤其是SqlConnection)保留在異步任務之外。
這個答案似乎使.NET認為IDiposables不在范圍內,因此在您仍嘗試使用它們時將其處置:
我可以通過刪除對第三方nuget lib的支持來解決我的問題,該第三方nuget lib刪除了我的連接。 盡管尚不清楚它為什么會發生,但擺脫所有異步調用並自己管理連接似乎已解決了我的問題。 批量導入工作正常,但是處理## Temp表中的數據很慢。 我決定將所有內容保留在內存中並從那里進行處理。
private bool Consume(byte[] fileByteArray, IDataProcess dataConsumer)
{
try
{
using (var conn = OpenConnection())
{
// Convert byte Array to a stream
Stream stream = new MemoryStream(fileByteArray);
// Create a reader from the stream
using (var reader = new CsvReader(stream, false, System.Text.Encoding.UTF8))
{
RecordEnumerator enumerator = reader.GetEnumerator();
enumerator.MoveNext();
do
{
// Proccess enumerator.Current with dataConsumer
} while (enumerator.MoveNext());
}
}
}
catch (Exception ex)
{
return false;
}
return true;
}
我們冒着內存不足的風險,但是在我們找到更快的方法之前,必須這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.