Я правильно использую DataContext.Dispose ()? - PullRequest
5 голосов
/ 16 ноября 2010

Я получаю много тайм-аутов пула соединений в моем проекте ASP.NET MVC. Я читал, что, хотя Linq-to-SQL должен избавляться от меня, это не всегда работает, а также то, что не выбрасывать вручную что-либо, наследующее IDisposable, - плохая практика.

Я использую шаблон репозитория, который используют все мои операторы Linq-to-SQL. Не зная, куда поместить метод DataContext.Dispose(), я поместил его в функцию SubmitChanges(), которая состоит из двух строк кода:

public void SubmitChanges()
{
    db.SubmitChanges();
    db.Dispose();
}

Это хорошее место, чтобы сделать это, или я делаю это совершенно неправильно?

Ответы [ 3 ]

8 голосов
/ 16 ноября 2010

Если он реализует IDisposable, самый простой способ сделать это:

using(var context = new DataContext()){
  blah blah
}

Это гарантирует, что он утилизируется в соответствующее время.

  1. Откройте его.
  2. Делайте то, что вам нужно.
  3. Закройте его.

Таким образом, вам не нужно беспокоиться о том, что он зависает, не вызывается из-за исключения и т. Д..

Ключевое слово dispose (MSDN Link) .

Поскольку они связаны, вот ссылка на Dispose and Finalize .Похоже, в этом случае вы хотите реализовать репозиторий, чтобы он реализовывал IDisposable.Таким образом, вызывающий объект может создать его, сделать то, что ему нужно, и закрыть его.После этого вы можете очистить контекст данных при его удалении / финализации.

2 голосов
/ 17 ноября 2010

Ну, после еще нескольких копаний я наткнулся на этот пост:

http://stephenwalther.com/blog/archive/2008/08/20/asp-net-mvc-tip-34-dispose-of-your-datacontext-or-don-t.aspx

и в разделе комментариев Крейг Штунц писал:

Failing to Disposeобъект, который реализует IDisposable, обычно приводит к тому, что объект попадает в очередь финализации (подробнее см. главу 19 «Прикладное программирование Microsoft .NET Framework Джеффри Рихтера»).Результатом этого является то, что память объекта, которая в противном случае могла бы быть освобождена в поколении 01, будет освобождена до коллекции более позднего поколения.Если вы создаете много этих объектов, хорошо, сделайте математику.

Таким образом, вы всегда должны располагать любым объектом, который реализует IDisposable.

В случае контроллеров и DataContexts, это превращаетсяЭто действительно просто, потому что Controller также реализует IDisposable, и, следовательно, имеет виртуальный метод Dispose, который вы можете переопределить.Таким образом, вам не нужно оборачивать использование DataContext в использование.Вы можете создать его в конструкторе (или где угодно), а затем разместить в переопределенном Controller.Dispose.В этом случае использование IQueryable в представлении работает просто отлично, поскольку среда не удаляет контроллер до тех пор, пока представление не будет отображено.

Итак, я сделал то, что предложил Крейг, и переопределил метод Dispose, чтобыController наследует.

В верхней части моего кода контроллера:

    Repository repository;

    // Default Contructor
    public MyController()
    {
        repository = new Repository();
    }

    protected override void Dispose(bool disposing)
    {
        repository.Dispose();
    }

и в моем репозитории у меня есть метод с именем Dispose, который выглядит следующим образом:

    public void Dispose()
    {
        db.Dispose();
    }

где db - мой DataContext.

Теперь мой переопределенный метод Dispose вызывается каждый раз :), и мне не нужно оборачивать все свои ActionResult при использовании блоков

1 голос
/ 16 ноября 2010

DataContext (ваш репозиторий) должен реализовывать IDisposable.

В идеале вам нужно UnitOfWork для передачи в репозитории, и это реализует IDisposable. Здесь вы оставляете клиенту вызов другого метода, который не годится .

...