2009-02-17 2 views
0

Фон: Я переписываю приложение VB6, которое использует MS Access для хранения данных в том, что использует VB.NET и MS SQL Server.Лучший способ передать объект соединения между формами?

Мне любопытно, как наилучшим образом передать соединение между различными формами в моем приложении, которым требуется подключение к базе данных. Сейчас я построил класс для управления строкой соединения так, что между формами безопасным способом:

Public Class LoginCredientials 
    Private uname As String 
    Private password_hash() As Byte = {0} 
    Private server_name As String 'not used in access style databases 
    Private dbname As String 
    Private st As ServerType 'enum that would allow for different connections 
    Private tdes As TripleDES 'encryption class to encrypt password in memory 

    Public Sub New() 
     uname = "" 
     server_name = "" 
     dbname = "" 
     st = ServerType.stNotDefined 
    End Sub 
    Public Sub New(ByVal Username As String, _ 
        ByVal Password As String, _ 
        ByVal ServerName As String, _ 
        ByVal DatabaseName As String, _ 
        ByVal ServType As ServerType) 
     tdes = New TripleDES 
     uname = Username 
     password_hash = tdes.Encrypt(Password) 
     server_name = ServerName 
     dbname = DatabaseName 
     st = ServType 
     tdes = Nothing 
    End Sub 

    Public ReadOnly Property Server_Type() As ServerType 
     Get 
      Return st 
     End Get 
    End Property 
    Public ReadOnly Property CompanyName() As String 
     Get 
      Return dbname.Remove(0, 4) 
     End Get 
    End Property 
    Public Property UserName() As String 
     Get 
      Return uname 
     End Get 
     Set(ByVal value As String) 
      uname = value 
     End Set 
    End Property 
    Public Property Password() As String 
     Get 
      tdes = New TripleDES 
      Return tdes.Decrypt(password_hash) 
      tdes = Nothing 
     End Get 
     Set(ByVal value As String) 
      tdes = New TripleDES 
      password_hash = tdes.Encrypt(value) 
      tdes = Nothing 
     End Set 
    End Property 
    Public Property ServerName() As String 
     Get 
      Return server_name 
     End Get 
     Set(ByVal value As String) 
      server_name = value 
     End Set 
    End Property 
    Public Property DatabaseName() As String 
     Get 
      Return dbname 
     End Get 
     Set(ByVal value As String) 
      dbname = value 
     End Set 
    End Property 

    Public Function GetConnectionString() As String 
     Dim cstring As String = "" 
     tdes = New TripleDES 
     Select Case st 
      Case ServerType.stSQLServer 
       cstring = "User ID=" & uname & ";" & _ 
         "Password=" & tdes.Decrypt(password_hash) & ";" & _ 
         "Initial Catalog=" & dbname & ";" & _ 
         "Data Source=" & server_name 
     End Select 
     tdes = Nothing 
     Return cstring 
    End Function 
End Class

я передавала ссылку на мой объект к любому из моих форм, которые необходимы подключение к базы данных, как так:

'in the form declaration 
Private myLC As LoginCredientials 
Public Sub New(ByRef lc As LoginCredientials) 
    InitializeComponent() 
    myLC = lc 
End Sub

а потом я хотел бы создать новый объект связи, сделал то, что мне нужно делать, а затем закрыл соединение и разрушил объект соединения. Когда я уже делал это раньше в ADO с VB6, процесс, созданный соединением, был убит, когда объект соединения был уничтожен, но, похоже, это не так. Теперь каждый раз, когда я создаю новый объект подключения и подключаюсь к моему серверу, создается новый процесс и затем усыпляется, когда я закрываю свое соединение. Через некоторое время сервер начнет отказывать в соединениях, пока я не войду в систему и не уничтожу все процессы, созданные моим приложением. Очевидно, это не делается правильно, и я хотел бы узнать правильный путь.

Было бы лучше просто передать один и тот же объект соединения по ссылке (или внутри класса-оболочки) среди моих форм, оставив объект соединения открытым?

Каков правильный способ закрыть мое соединение, чтобы в конечном итоге не получить кучу спальных процессов на моем SQL-сервере? Есть ли настройка на SQL-сервере, которую я могу настроить для автоматического отключения процессов после определенного периода бездействия?

Вы считаете, что шифрование пароля в избыточном избытке памяти?

Благодарим за помощь. :)

+0

Вы когда-нибудь рассматривали возможность использования Enterprise Library для подключения к данным? http://www.codeplex.com/entlib – Walter

ответ

8

Вы НЕ должен передать объект соединения между формами. В принципе, шаблон при использовании соединения с SQL Server заключается в создании соединения, его открытии, выполнении операции, а затем закрытии соединения.

Для этого вы должны иметь публичный статический метод где-то, который будет генерировать свой SqlConnection, который вы будете использовать в Используя заявление, например, так:

Using connection As SqlConnection = GetConnection 
    ' Use connection here. 

End Using 

Это должно предотвратить процессы от укладки до на сервер.

+0

Никогда раньше не пробовал это, но это имеет гораздо больше смысла, чем то, что у меня было в голове. Я сделаю это, спасибо! –

+0

Скажите, что вам нужно позвонить в более, чем 100 раз, тогда вам нужно будет открыть 100 подключений. Чтобы предотвратить то, что вам нужен контекст более высокого уровня для вашего соединения, которое может быть общим. Иначе это отлично работает. – Middletone

+0

@Middletone: Я согласен, но нужно принять ОЧЕНЬ строгие меры, чтобы убедиться, что соединение обработано правильно. Одинокая идея - это просто общение. Вы должны создать соединение, а затем передать его подпрограмме, которая будет выполнять итерацию. – casperOne

1

Вы можете использовать оператор Using, он будет закрывать и удалять соединение при его завершении.

Using _conn as New SqlConnection(<connstring>) 
    _conn.Open() 
    'get your data' 

End Using 

Если вы не являетесь авентирующим. Закройте(), это может быть проблемой.

1

Я согласен с Каспер. Если вам нужно разделить объект между страницами, чтобы уменьшить нагрузку, например, вы можете использовать статическую переменную-член для этого. Просто не забудьте закрыть соединение, когда последний оператор был выполнен. Вы также можете создать область подключения, которая может быть удалена после завершения последней транзакции. Если у вас нет опыта для этого, просто откройте и закройте свое соединение при первой же возможности и не пропустите его.

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

+0

Спасибо, я сделаю это. –

1

Будучи это VB.NET, который вы используете, попробуйте это (код из памяти, не копируется из приложения):

Namespace Helpers 

Public NotInheritable Class Connections 

    Private Sub New() 

    End Sub 

    Public Shared Function GetConnection(ByVal connString As String) As SqlConnection 
     Dim c as New SqlConnection(connString) 
     c.Open 
     Return c 
    End Sub 

    Public Shared Sub AdoCleanup(cn As SqlConnection, cmd As SqlCommand) 
     cmd.Dispose 
     cn.Close 
    End Sub 

End Class 

End Namespace 

И затем использовать его так:

Private Sub LoadMyData() 

    Dim connString As String = <your conn string> 
    Dim cn As SqlConnection = Helpers.Connections.GetConnection(connString) 
    Dim cmd As New SqlCommand 

    Try 
     ' data access code 
    Catch ex As Exception 
     ' handle exception 
    Finally 
     Helpers.Connections.AdoCleanup(cn, cmd) 
    End Try 

End Sub 

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

+0

Благодарим вас за помощь. Я могу попробовать это, так как будет несколько ситуаций, когда мне потребуется больше одного подключения. Так много способов делать вещи! –

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