Можно ли получить утечки соединения SQL с помощью LINQ? - PullRequest
6 голосов
/ 23 апреля 2009

Я полагал, что при использовании LINQ невозможно получить утечки из sql-соединения, но трассировка числа NumberOfReclaimedConnections показывает большое число, и при высокой нагрузке мы иногда получаем исключения, такие как «Истекло время ожидания. пул. Это могло произойти из-за того, что все пулы подключений использовались и был достигнут максимальный размер пула ".

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

И все же иногда мы получаем эти исключения. Но не может быть так, чтобы каждый запрос linq, который мы сохраняли, открывал соединение, тогда у нас было бы намного больше исключений.

Отредактировано

Приложение является службой WCF.

Если вы посмотрите документацию Linq и большинство статей, они утверждают, что Dispose не нужен для освобождения соединений. Они утверждают, что DataCOntext сохраняет соединение открытым только в течение короткого времени, в котором оно необходимо.

Ответы [ 3 ]

10 голосов
/ 23 апреля 2009

Когда ваш DataContext не утилизируется и остается в живых, соответствующее соединение также останется в живых. Соединения с базой данных являются неуправляемыми ресурсами, и все неуправляемые ресурсы должны быть утилизированы надлежащим образом.

Даже если вы используете задержку загрузки и не имеете четко определенной области действия, вы все равно должны очистить соединения с базой данных в конце логической единицы работы. В приложениях ASP.NET последний возможный момент для этого будет в конце обработки запроса - в методе Application_EndRequest файла Globals.asax. В службе WCF любой активный контекст данных должен удаляться в конце каждого вызова метода службы.

Документация по этому вопросу является расплывчатой, и, хотя большую часть времени вы можете обойтись без утилизации DataContext, существуют некоторые сценарии, когда данные, загруженные из соединения, поддерживают само соединение живым. Самый простой способ подтвердить, что это происходит в вашем случае, это проверить его.

4 голосов
/ 23 апреля 2009

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

Я сделал этот небольшой тестовый код, который воспроизводит его. Если я просто заменяю Enumerator на foreach, он работает нормально, но он Enumerator сохраняет соединения открытыми.

public Organisation RunTestQuery2()
{
    IEnumerable<Organisation> orgs  = base.GetEntities<Organisation>().Take(5);

    var enumerator = orgs.GetEnumerator();
    int i = 0;


    while (enumerator.MoveNext())
    {
        var org = enumerator.Current;
        Debug.WriteLine(org.DescribingName);
        if (i == 3)
        {
           return org;
        }
        i++;
    }

    return null;
}

Если я добавлю вызов в распоряжение контекста, они исчезнут.

0 голосов
/ 23 апреля 2009

Есть ли у вас тупики в вашей базе данных? Беглый взгляд на Activity Monitor должен дать вам некоторое представление.

Что вы делаете для управления жизненным циклом DataContext - какое приложение вы написали (веб-сайт, клиент Windows и т. Д.)?

После использования в запросе или операции DataContext будет сохранять соединение, чтобы загруженные объекты могли загружаться лениво и т. Д., Поэтому крайне важно спланировать, как вы используете DataContexts в своем приложении.

Службы WCF. В этом случае я большой поклонник подхода «один контекст на запрос». Я бы посоветовал вам обернуть свои операции с данными в оператор using (), чтобы контекст был удален, когда вы закончите.

...