EF 6 Пул соединений и хранимые строки запросов Утечка ОЗУ - PullRequest
4 голосов
/ 20 марта 2020

У меня 2 проблемы.

Во-первых, пул соединений и (OracleConnectionImpl) неуклонно растут с течением времени, пока не достигнет исключения из памяти. Как вы можете видеть на изображении, у него 90 МБ за 3-4 часа работы.

Я везде использую краткосрочные контексты, но он продолжает расти и никогда не очищается. Можно ли как-нибудь это очистить?

Во-вторых, EF со временем сохраняет слишком много дубликатов строковых запросов. Он в основном хранит те, которые поступают из функции .Reload (), поскольку он не параметризуется, он жестко кодирует идентификатор в запросе. Кроме того, есть строки типа «ID», которые где-то кэшируются 2947x.

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

Это приложение обновляет складские задания и паллеты каждые несколько секунд, чтобы поддерживать его синхронизацию c для всех машин, и я не знаю лучшего способа, чем .Reload () из-за привязок WPF.

dotMemory Snapshot

String duplicates

Редактировать 1

У меня есть простая вспомогательная функция для одновременной загрузки многих объектов, даже одно расширение. Неважно, что он передается как объект, потому что та же проблема сохраняется даже в последнем примере.

     public static void ReloadEntities(bool dispatch, params IEnumerable<object>[] entities)
        {
            using (var ctx = new eWMSEntities())
            {
                if (dispatch)
                {
                    Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, (SendOrPostCallback)delegate
                    {
                        entities.SelectMany(x => x.Select(s => s)).ToList().ForEach(entity =>
                       {
                           ctx.Set(entity.GetType()).Attach(entity);
                           ctx.Entry(entity).Reload();
                           ctx.Entry(entity).State = EntityState.Detached;
                       });
                    }, null);
                }
                else
                {
                    entities.SelectMany(x => x.Select(s => s)).ToList().ForEach(entity =>
                    {
                        ctx.Set(entity.GetType()).Attach(entity);
                        ctx.Entry(entity).Reload();
                        ctx.Entry(entity).State = EntityState.Detached;
                    });
                }
                ctx.Dispose();
            }
        }

        public static void ReloadEntity(this object entity, bool dispatch)
        {
            using (var ctx = new eWMSEntities())
            {
                ctx.Set(entity.GetType()).Attach(entity);
                if (dispatch)
                {
                    Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, (SendOrPostCallback)delegate
                    {
                        ctx.Entry(entity).Reload();
                    }, null);
                }
                else
                {
                    ctx.Entry(entity).Reload();
                }
                ctx.Entry(entity).State = EntityState.Detached;
                ctx.Dispose();
            }
        }
    while (true && JobLines.Contains(line))
            {
                using (var ctx = new eWMSEntities())
                {
                    ctx.T_JOB_LINES.attach(line);
                    ctx.entry(line).Reload();
                }
await Task.Delay(3000);
            }

Это снимок после 3 дней работы Snapshot

Ответы [ 2 ]

0 голосов
/ 30 марта 2020

Используйте шаблон «Единица работы» - он решит многие проблемы. Я не нашел для WPF, но нашел для ASP. NET MVC

0 голосов
/ 27 марта 2020

Я не рекомендую, но если нет другого решения ... Может быть, вы можете попробовать

GC.Collect();

Пусть система принудительно соберет что-то не важное в вашей памяти.

...