Я пропускаю соединения ADO.NET? - PullRequest
4 голосов
/ 12 апреля 2010

Вот пример моего кода в DAL. Все вызовы хранимых процедур базы данных структурированы таким образом, и встроенного SQL нет.

Friend Shared Function Save(ByVal s As MyClass) As Boolean

    Dim cn As SqlClient.SqlConnection = Dal.Connections.MyAppConnection
    Dim cmd As New SqlClient.SqlCommand

    Try
        cmd.Connection = cn
        cmd.CommandType = CommandType.StoredProcedure
        cmd.CommandText = "proc_save_my_class"

        cmd.Parameters.AddWithValue("@param1", s.Foo)
        cmd.Parameters.AddWithValue("@param2", s.Bar)

        Return True

    Finally
        Dal.Utility.CleanupAdoObjects(cmd, cn)
    End Try

End Function

Вот фабрика соединений (если я использую правильный термин):

Friend Shared Function MyAppConnection() As SqlClient.SqlConnection

    Dim cn As New SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("MyConnectionString").ToString)
    cn.Open()

    If cn.State <> ConnectionState.Open Then
        ' CriticalException is a custom object inheriting from Exception.
        Throw New CriticalException("Could not connect to the database.")
    Else
        Return cn
    End If

End Function

Вот функция Dal.Utility.CleaupAdoObjects ():

Friend Shared Sub CleanupAdoObjects(ByVal cmd As SqlCommand, ByVal cn As SqlConnection)
    If cmd IsNot Nothing Then cmd.Dispose()
    If cn IsNot Nothing AndAlso cn.State <> ConnectionState.Closed Then cn.Close()
End Sub

Я получаю много сообщений: «Время ожидания истекло. Время ожидания истекло до завершения операции, или сервер не отвечает». сообщения об ошибках, сообщаемые пользователями. DAL приложения открывает соединение, считывает или сохраняет данные и закрывает его. Нет открытых соединений - намеренно!

На Windows 2000 Server, на котором установлен SQL Server 2000, нет ничего очевидного, что указывало бы на проблему. Ничего в журналах событий и ничего в журналах SQL Server.

Тайм-ауты случаются случайно - я не могу воспроизвести. Это происходит в начале дня, когда в системе всего от 1 до 5 пользователей. Это также происходит с примерно 50 пользователями в системе. Наибольшее количество подключений к SQL Server через системный монитор для всех баз данных составляет около 74.

Тайм-ауты происходят в коде, который одновременно сохраняет и читает из базы данных в различных частях приложения. Трассировка стека не указывает на одну или две ошибочные функции DAL. Это случилось во многих разных местах.

Может ли мой код ADO.NET пропускать соединения? Я немного прогулялся и прочитал, что, если пул соединений заполняется, это может произойти. Тем не менее, я не устанавливаю явно пул соединений. Я даже пытался увеличить время ожидания подключения в строке подключения, но время ожидания наступает задолго до значения 300 секунд (5 минут):

<add name="MyConnectionString" connectionString="Data Source=MyServer;Initial Catalog=MyDatabase;Integrated Security=SSPI;Connection Timeout=300;"/>

Я уже в полной растерянности относительно того, что вызывает эти проблемы с тайм-аутом. Любые идеи приветствуются.

РЕДАКТИРОВАТЬ: Это приложение WinForms.

Ответы [ 5 ]

3 голосов
/ 13 апреля 2010

Один из способов проверить наличие утечек соединения - добавить max pool size в строку подключения, например:

"integrated security=SSPI;server=MyHost;Max Pool Size=1;"

В разработке я обычно запускаю с этим параметром (или размером 2, если приложение использует два соединения одновременно).

2 голосов
/ 14 апреля 2010

С здесь :

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

SqlConnection, SqlCommand, SqlDataReader и т. Д. ... все реализуют IDisposable. Если вы вложите все эти экземпляры в блок Using, автоматически будет вызван Dispose, ваши соединения будут закрыты, и вам не придется беспокоиться о таких проблемах. Запустите рефлектор и посмотрите сами: (SqlConnection.Dispose)

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}

Это также делает код короче, так как вам не нужно вручную добавлять блок finally для очистки ваших объектов ADO.NET.

Using connection As SqlConnection("your connection string")
    Using command As New SqlCommand("your sql", connection)
        connection.Open()
        Using dataReader As SqlDataReader = command.ExecuteReader()
            'Your stuff here
        End Using
    End Using
End Using

Использование подхода Using заставляет вас сохранять объекты ADO.NET локальными, что для меня хорошо.

1 голос
/ 13 апреля 2010

Вы всегда должны утилизировать соединение, независимо от его состояния:

 'If cn IsNot Nothing AndAlso cn.State <> ConnectionState.Closed Then cn.Close()
 If cn IsNot Nothing Then cn.Dispose()

Я не уверен, что это может привести к тайм-ауту, но это, безусловно, улучшение.

0 голосов
/ 13 апреля 2010

Это приложение для Windows или веб-приложение?

Тайм-ауты случаются с простыми хранимыми процедурами или просто с более сложными?

Вы пытались запустить трассировку sql profiler, чтобы увидеть, действительно ли какие-либо запросы занимают много времени?

Кроме того, вы пытались конвертировать в синтаксис "using", который гарантирует, что объекты закрываются и утилизируются должным образом?

0 голосов
/ 13 апреля 2010

Как ваши хранимые процедуры работают вне вашего приложения?

Что если вы переместили 'return true' из блока try / finally в Save ()?

Мониторинг соединений с БД в perf-мониторе, чтобы увидеть, растут ли они.

Но первое, на что я бы обратил внимание, это сами ваши спрокеры - они обращаются к таблицам в согласованном порядке или у вас могут быть блокировки? Например, если proc1 манипулирует таблицей1, а затем таблицей2, тогда как proc2 обращается к таблице2, а затем к таблице1, вы можете столкнуться с проблемами блокировки.

...