Как очистить / сбросить ObjectContext в EF 4 - PullRequest
0 голосов
/ 27 марта 2011

У меня есть иерархическая структура с миллионами записей.Я делаю рекурсивное сканирование БД, чтобы обновить некоторые соединения и некоторые данные.проблема в том, что я получаю исключение вне памяти, так как вся БД в конечном итоге загружается в контекст (ленивый).данные, которые мне больше не нужны, остаются в контексте без какого-либо способа их удаления.Я также не могу использовать Using (context ...), так как мне нужен живой контекст, потому что я делаю рекурсивное сканирование.

Пожалуйста, примите рекурсию как факт.Спасибо

Ответы [ 2 ]

2 голосов
/ 01 мая 2011

просто столкнулся с той же проблемой.Я использовал NHibernate до того, как использовал EF в качестве инструмента ORM, и у него была точно такая же проблема.Эти структуры просто сохраняют объекты в памяти до тех пор, пока контекст жив, что имеет два последствия:

  • серьезное снижение производительности: среда выполняет сравнения между объектами в памяти (например, чтобы увидетьсуществует ли объект или нет).Вы заметите постепенное ухудшение производительности при обработке многих записей

  • у вас в конечном итоге не хватит памяти.

Если возможно, я всегда стараюсьделать большие пакетные операции с базой данных, используя чистый SQL (как ясно сказано в посте выше), но в этом случае это было невозможно.Чтобы решить эту проблему, NHibernate имеет метод «Очистить» в сеансе, который отбрасывает все объекты в памяти, которые ссылаются на записи базы данных (новые, добавленные, поврежденные ...). Я попытался имитировать этот метод вСтруктура сущностей выглядит следующим образом (с использованием поста, описанного выше):

    public partial class MyEntities
    {

        public IEnumerable<ObjectStateEntry> GetAllObjectStateEntries()
        {
            return ObjectStateManager.GetObjectStateEntries(EntityState.Added |
                                                        EntityState.Deleted |
                                                        EntityState.Modified |
                                                        EntityState.Unchanged);
        }

        public void ClearEntities()
        {
            foreach (var objectStateEntry in GetAllObjectStateEntries())
            {
                Detach(objectStateEntry.Entity);
            }
        }
    }

Метод GetAllObjectStateEntries () взят отдельно, потому что он полезен для других целей.Это относится к частичному классу с тем же именем, что и у вашего класса Entities (тот, который генерирует EF, в этом примере MyEntities), так что он доступен в вашем экземпляре entity.

Я вызываю этот метод clear теперь каждые 1000 записейЯ обрабатываю, и мое приложение, которое раньше работало в течение около 70 минут (обрабатывается только около 400 000 объектов, даже не миллионы), делает это за 25 минут.Память использовалась до пика до 300 МБ, теперь она составляет около 50 МБ

2 голосов
/ 27 марта 2011

Операции такого рода на самом деле плохо обрабатываются и не масштабируются с использованием сущностей.Я склонен прибегать к хранимым процедурам для пакетных операций.

Если вы хотите удалить / вывести объекты из контекста, я считаю, в этом посте есть некоторая информация (решение вашей проблемы внизу).).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...