Должен ли я хранить экземпляр DbContext в отдельном потоке, который выполняет периодические задания

#c# #.net #asp.net #multithreading #entity-framework-4

#c# #.net #asp.net #многопоточность #entity-framework-4

Вопрос:

У меня есть класс Worker, который периодически отправляет электронные письма, я запускаю в Global.asax.cs в App_start()

 public static class Worker
{
    public static void Start()
    {
        ThreadPool.QueueUserWorkItem(o => Work());
    }

    public static void Work()
    {
        var r = new DbContext();
        var m = new MailSender(new SmtpServerConfig());
        while (true)
        {
            Thread.Sleep(600000);
            try
            {
                var d = DateTime.Now.AddMinutes(-10);
                var ns = r.Set<Notification>().Where(o => o.SendEmail amp;amp; !o.IsRead amp;amp; o.Date < d);

                foreach (var n in ns)
                {
                    m.SendEmailAsync("noreply@example.com", n.Email, NotifyMailTitle(n)   " - forums", NotifyMailBody(n));
                    n.SendEmail = false;
                }

                r.SaveChanges();
            }
            catch (Exception ex)
            {
                ex.Raize();
            }
        }
    }
 }
  

Итак, я сохраняю этот dbcontext в течение всего срока службы приложения, это хорошая практика?

Ответ №1:

DbContext — очень легкий объект.

Не имеет значения, остается ли ваш DbContext живым или вы создаете его непосредственно перед выполнением вызова, потому что фактическое соединение с БД открывается только тогда, когда вы отправляете изменения или перечисляете запрос (в этом случае он закрывается в конце перечисления).

В вашем конкретном случае. Это не имеет никакого значения.

Прочитайте Linq DataContext и Dispose для получения подробной информации об этом.

Ответ №2:

Я бы обернул его в using инструкцию внутри Work и позволил пулу подключений к базе данных делать это:

  using (DbContext r = new DbContext())
 {
     //working
 }
  

ПРИМЕЧАНИЕ: я не уверен на 100%, как DbContext обрабатывает соединения с БД, я предполагаю, что он открывает один.

Не рекомендуется поддерживать «живое» соединение с базой данных в течение всего срока службы приложения. Вы должны использовать соединение, когда это необходимо, и закрыть его через API (using statement позаботится об этом за вас). Пул подключений к базе данных фактически открывает и закрывает соединения на основе требований к подключению.

Ответ №3:

Я согласен с @rick schott в том, что вы должны создавать экземпляр DbContext , когда вам нужно его использовать, а не хранить его в течение всего срока службы приложения. Для получения дополнительной информации см. раздел Работа с объектами (Entity Framework 4.1), особенно раздел о времени жизни:

При работе с длительным контекстом учитывайте следующее:

  • По мере загрузки большего количества объектов и их ссылок в память потребление памяти контекстом может быстро увеличиваться. Это может вызвать проблемы с производительностью.

  • Если исключение приводит к тому, что контекст находится в невосстановимом состоянии, все приложение может завершиться.