2010-04-21 4 views
5

Я инкапсулирую свои linq в вызовы sql в классе репозитория, который создается в конструкторе моего перегруженного контроллера. Конструктор моего класса репозитория создает контекст данных, так что для жизни загрузки страницы используется только один контекст данных.Почему мои соединения не закрыты, даже если я явно удаляю DataContext?

В моем деструкторе класса репозитория я явно вызываю утилиту DataContext, хотя я не считаю, что это необходимо.

Использование монитора производительности, если я наблюдаю, как мои соединения с пользователем подсчитываются и многократно загружают страницу, число увеличивается один раз на загрузку страницы. Соединения не закрываются или не используются (около 20 минут).

Я попытался положить Pooling = false в мою конфигурацию, чтобы убедиться, что это не повлияло, но это не так. В любом случае с пулом я бы не ожидал нового подключения для каждой нагрузки, я бы ожидал, что он будет повторно использовать соединения.

Я попытался поставить точку останова в деструкторе, чтобы убедиться, что у вас есть цель, и это действительно так. Так что происходит?

Часть кода, чтобы проиллюстрировать то, что я сказал выше:

Контроллер:

public class MyController : Controller 
{ 
    protected MyRepository rep; 

    public MyController() 
    { 
     rep = new MyRepository(); 
    } 
} 

Репозиторий:

public class MyRepository 
{ 
    protected MyDataContext dc; 

    public MyRepository() 
    { 
     dc = getDC(); 
    } 

    ~MyRepository() 
    { 
     if (dc != null) 
     { 
      //if (dc.Connection.State != System.Data.ConnectionState.Closed) 
      //{ 
      // dc.Connection.Close(); 
      //} 
      dc.Dispose(); 
     } 
    } 

    // etc 
} 

Примечание: добавить несколько подсказок и контекстной информации в DC для целей аудита. Это, по существу, почему я хочу одно соединение на странице загрузки

Update: После реализовав IDisposable на моем хранилище и на моем классе контроллера я не мог найти способ специально вызвать метод Dispose на мой контроллер, что и контроллер создается и уничтожается за кулисами MvcHandler. Однако я обнаружил, что мои связи все равно закрываются. Я не комфортно, зная, что это работает, но не зная, почему, так что я сделал некоторые раскопки и нашел цитату MSDN, которая сделала меня счастливым:

Когда исполнение завершено, MvcHandler будет проверять, если контроллер реализует IDisposable интерфейс, и если это так, вызывается Dispose на контроллере для очистки неуправляемых ресурсов.

Final Update: Через месяц или около того с работой этого я теперь удалены весь этот код и пошел вниз MS посоветовал маршрут оборачивать «используя» заявление вокруг кода в моих методах общественного хранилища и передача этого DC в частные методы. Это кажется немного расточительным и повторяющимся, а также приводит к открытию и закрытию еще нескольких соединений. Но я получал linq для кэширования sql, что я мог решить только путем сброса DC.

ответ

4

Правильный шаблон (короткий, но достаточный вариант) здесь:

public class MyRepository : IDisposable 
{ 
    ... // everything except the dtor 

    public void Dispose() 
    { 
     if (dc != null) 
     { 
      dc.Dispose(); 
     } 
    } 
} 

public class MyController : Controller, IDisposable 
{ 
    protected MyRepository rep; 

    public MyController() 
    { 
     rep = new MyRepository(); 
    } 

    public void Dispose() 
    { 
     if (rep!= null) 
     { 
      rep.Dispose(); 
     } 
    } 
} 

И теперь вы можете (должны) использовать MyController с помощью пункта:

using (var ctl = new MyController()) 
{ 
    // use ctl 
} 

Edit:
Просто заметил это каскады к MyController, добавлен код. Это показывает, как распространяется косвенное владение неуправляемым ресурсом.

Edit 2:
Это тоже правильно (как бы попытка/наконец):

var ctl = GetController(); 
using (ctl) 
{ 
    // use ctl 
} 

Если вы не можете держать его местный 1 метод, просто сделать все возможное, чтобы позвонить CTL .Dispose() в событии закрытия или таковой.

+0

ах, спасибо. Мне просто интересно, нужен ли мой код для добавления (ссылаясь на редактирование) –

+0

Я не уверен в последнем бит. MVC генерирует мой контроллер, и как я могу обеспечить его правильное расположение? –

+0

@ Крис, будьте осторожны при наследовании, я замечаю, что вы защитили поля. Я бы этого не сделал. –

2

Деструкторы вызываются только GC. Ваш MyRepository должен реализовать шаблон Dispose и утилизировать там dc.

См. Этот вопрос для получения более подробной информации. In C# what is the difference between a destructor and a Finalize method in a class?

MyRepository должен реализовывать IDisposable, любые удаляемые объекты должны быть удалены там, если вы держите их открытыми для срока службы объекта.

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

т.е.

using(var dc = getDC()) 
{ 
    //do stuff with the dc 
}//the dc will be Disposed here 

Редактировать: Ссылка на языке руководство по C# деструкторы http://msdn.microsoft.com/en-us/library/66x5fx1b(v=VS.100).aspx

+0

И __not__ реализовать деструктор. Это нецелесообразно в этом классе. –

+0

ahh, вы говорите, что Dispose не следует вызывать в деструкторе? –

+0

Согласованные деструкторы должны редко использоваться в приложении C#. –

0

Я согласен с тем, что одноразовые предметы были неправильными, а предложения, приведенные выше, Henk Holterman и Darryl Braaten - очень хорошие, я не думаю, что он отвечает на ваш основной вопрос.

Ответ на ваш вопрос заключается в том, что вызов Dispose в MyRepository (при условии, что его DataContext) не закрывает соединение. Он просто возвращает соединение с пулом для следующего использования.

This SO Post, объясняет, когда вы должны беспокоиться о закрытии соединения ...

+0

Исходный вопрос уже касается объединения («Соединения не закрываются или повторно используются ...») –

+0

Не могли бы вы переписать это? Я не следую? – Nix

+0

Не похоже, что соединение возвращается в пул. Независимо от того, включено или выключено объединение пула, новые соединения всегда выполняются и не используются повторно. –

Смежные вопросы