Как уменьшить объем памяти с помощью больших наборов данных в EF5?
Я пытаюсь вытащить большой набор данных (1,4 миллиона записей) из SQL Server и дампа в файл в приложении WinForms. Я попытался сделать это с помощью подкачки, чтобы не держать слишком много в памяти сразу, но процесс продолжает расти, поскольку он работает. Около 25% через, это занимало 600,000 K. я делаю пейджинг неправильно? Могу ли я получить некоторые предложения о том, как сохранить использование памяти от роста так много?
var query = (from organizations in ctxObj.Organizations
where organizations.org_type_cd == 1
orderby organizations.org_ID
select organizations);
int recordCount = query.Count();
int skipTo = 0;
int take = 1000;
if (recordCount > 0)
{
while (skipTo < recordCount)
{
if (skipTo + take > recordCount)
take = recordCount - skipTo;
foreach (Organization o in query.Skip(skipTo).Take(take))
{
writeRecord(o);
}
skipTo += take;
}
}
4 ответов
избавиться от подкачки и использовать AsNoTracking
.
Тестовый Код
static void Main(string[] args)
{
var sw = new Stopwatch();
sw.Start();
using (var context = new MyEntities())
{
var query = (from organizations in context.LargeSampleTable.AsNoTracking()
where organizations.ErrorID != null
orderby organizations.ErrorID
select organizations);//large sample table, 146994 rows
foreach (MyObject o in query)
{
writeRecord(o);
}
}
sw.Stop();
Console.WriteLine("Completed after: {0}", sw.Elapsed);
Console.ReadLine();
}
private static void writeRecord(ApplicationErrorLog o)
{
;
}
Результат Теста:
потребление памяти уменьшено: 96%
Время выполнения сокращено:50%
толкование
AsNoTracking предоставляет преимущества для использования памяти по очевидным причинам, нам не нужно поддерживать ссылки на объекты, когда мы загружаем их в память. Объекты практически сразу становятся доступными. Объединить ленивый оценке и AsNoTracking, и нет необходимости в пейджинге, и уничтожение контекста может быть отложено.
хотя это один тест, большое количество строк и исключение большинства внешних факторов делают это хорошим представлением для общего случая.
контекст объекта будет хранить объекты в памяти, пока он не будет удален. Я бы рекомендовал удалить контекст после каждой партии, чтобы предотвратить дальнейшее увеличение объема памяти.
вы также можете использовать AsNoTracking()
(http://msdn.microsoft.com/en-us/library/gg679352(В=и 103).аспн), поскольку не сохраняются в базе данных.
несколько вещей.
вызов
Count()
выполнить запрос. Затем запустить его второй раз, чтобы получить результаты. Тебе не нужно этого делать.память, которую вы видите, связана с загрузкой объектов в память. Если вам нужно только подмножество полей, проецируйте на анонимный тип (или более простой именованный тип.) Это позволит избежать любых изменений отслеживания и накладных расходов.
используется таким образом, EF может быть хорошим строго типизированным API легкий SQL-запросов.
что-то вроде этого должно сделать трюк:
var query = from organizations in ctxObj.Organizations
where organizations.org_type_cd == 1
orderby organizations.org_ID
select new { o.Id, o.Name };
foreach (var org in query)
{
write(org.Id, org.Name);
}
почему бы вам просто не использовать стандартный System.Data.SqlClient.SqlConnection
класса? Вы можете прочитать результаты командной строки по строкам, используя SqlDataReader
class и запишите каждую строку в файл. У вас есть полный контроль, чтобы гарантировать, что ваш код ссылается только на одну строку записей за раз.
using (var writer = new System.IO.StreamWriter(fileName))
using (var conn = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand())
{
cmd.CommandText = "SELECT * FROM Organizations WHERE org_type_cd = 1 ORDER BY org_ID";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
int id = (int)reader["org_ID"];
int org_type_cd = (int)reader["org_type_cd"];
writer.WriteLine(...);
}
}
}
}
Entity Framework не предназначен для решения каждой проблемы или быть вашим эксклюзивным фреймворком доступа к данным. Это означает, что вещи проще писать для простых операций CRUD. Работа с миллионами строк-это хороший вариант использования для более специализированного решения.