I have a class that uses the SqlBulkCopy to bulk insert data into a SQL Server database. My original implementation just passed the m_buffer
(which is a reference to a class that implements IDataReader) directly into the WriteToServer
. Now a new requirement has been added that, upon failure, the process should retry the Bulk Insert command. Why you ask? Because one of our clients get intermittent SQL exceptions because they have crappy hardware.
Okay, I digress, since IDataReader is read-once I needed to come up with something different. I chose to load the IDataReader into a DataTable first and then pass the DataTable into the WriteToServer
method. Now my problem is that I will be using more memory and since I do not know anything about the data (the number of columns nor the amount of data in each row) I wanted to attempt to make the code safe from an OutOfMemoryException.
Unfortunately I could not find a good way to determine the amount of available memory, so instead I chose to dump the data every 50,000 rows or when the memory allocation reaches an arbitrary number (1 gig), whichever comes first.
Does this sound like a sound approach or is there a better way?
// m_buffer is a read-once cache (implements IDataReader) that pulls
// data from an external source as needed so it uses very little memory.
// My original implementation just used m_buffer as the parameter of
// WriteToServer but now I have to add retry logic into the process.
// The retry logic is in the PutDataIntoDatabase method.
const long MAX_MEMORY_TO_USE = 1073741824; // 1 gig
DataTable dataTable = new DataTable(m_tableName);
foreach (DataField d in m_buffer.GetColumns())
dataTable.Columns.Add(new DataColumn(d.FieldName, d.FieldType));
while (m_buffer.Read())
{
DataRow row = dataTable.NewRow();
for (int i = 0; i < m_buffer.FieldCount; i++)
row[i] = m_buffer.GetValue(i);
dataTable.Rows.Add(row);
long totalMemory = GC.GetTotalMemory(false);
if (rowCount++ > 50000 || totalMemory > MAX_MEMORY_TO_USE)
{
PutDataIntoDatabase(dataTable);
dataTable.Clear();
rowCount = 0;
}
}
if (dataTable.Rows.Count > 0)
PutDataIntoDatabase(dataTable);
taskmgr.exe
knows that info, then there must be a way. veskokolev.blogspot.com/2008/03/… \$\endgroup\$IDataReader
) look like? Is a network source, a file source, or anything else? \$\endgroup\$