У меня проблема с утечкой памяти в сервисной программе, которая запускает SQL-скрипты и выгружает результаты в файлы. После выполнения запросов, которые производят множество строк результатов, использование памяти в процессе увеличивается на 50 + МБ каждый раз и не уменьшается.Утечка памяти с .NET SqlConnection и DataSet
Вот код, который открывает соединение и возвращает результаты:
using (var conn = new SqlConnection(DataSourceInfo.ConnectionString))
{
conn.Open();
var scmd = new SqlCommand(query_string, conn);
scmd.CommandTimeout = 86400;
var writer = dest.GetStream(); //the writer is disposed of elsewhere
using (var da = new SqlDataAdapter(scmd))
using (var ds = new DataSet())
{
da.Fill(ds);
var table = ds.Tables[0];
var rows = table.Rows;
if (TaskInfo.IncludeColNames.Value)
{
object[] cols = new object[table.Columns.Count];
for(int i = 0; i < table.Columns.Count; i++)
cols[i] = table.Columns[i];
LineFormatter(writer, TaskInfo.FieldDelimiter, null, false, cols);
writer.WriteLine();
}
foreach(System.Data.DataRow r in rows)
{
var fields = r.ItemArray;
LineFormatter(writer, TaskInfo.FieldDelimiter, TaskInfo.TextQualifier, TaskInfo.TrimFields.Value, fields);
writer.WriteLine();
}
}
}
Я использовал WinDbg с SOS.dll в список лучших объектов по типу после выполнения было завершено, и процесс было достаточно времени, чтобы GC:
79333470 101 166476 System.Byte[]
65245dcc 177 3897420 System.Data.RBTree`1+Node[[System.Data.DataRow, System.Data]][]
0015e680 5560 3968936 Free
79332b9c 342 3997304 System.Int32[]
6524508c 120349 7702336 System.Data.DataRow
793041d0 984 22171736 System.Object[]
7993bec4 70 63341660 System.Decimal[]
79330a00 2203630 74522604 System.String
Второй столбец - это количество объектов, а третий - общий размер.
Не должно быть никаких объектов System.Data.DataRow. Похоже, что они каким-то образом просочились, но я не знаю, как это сделать.
Что я делаю неправильно?
Примечание: в предыдущей версии SqlDataReader использовался для получения данных о строках, но в этом подходе не было возможности получить заголовки столбцов (что я знаю), и обмен данными между DataSet и SqlDatReader будет бесшумно прерываться при выполнении некоторых запросов , Я не помню эту версию с проблемой утечки памяти.
Мне кажется странным. Просто пунт, попробовали ли вы обернуть свой 'SqlCommand' в' using' statement? – kbrimington
Вы пытались позвонить GC.Collect(), чтобы убедиться, что DataRows являются коллекционируемыми в первую очередь? IIRC, GC не собирает, пока у него не будет давления памяти для этого. – Amy
По какой-то причине я думал, что SqlCommand не является одноразовым.Я поставлю его в разделе using, но проблема, похоже, пропорциональна размеру запроса. Я думаю, что предложения о том, что GC фактически не происходят, могут быть правильными. Я проверю его, как только у меня появится шанс. –