Background: I'm rewriting a VB6 app that used MS Access for data storage to one that uses VB.NET and MS SQL Server.
I'm curious as to the best way to pass a connection among the different forms in my application that need a connection to the database. Right now I've built a class to manage the connection string to pass that between forms in a secure manner:
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
I had been passing a reference to my object to any of my forms that needed a connection to the database like so:
'in the form declaration Private myLC As LoginCredientials Public Sub New(ByRef lc As LoginCredientials) InitializeComponent() myLC = lc End Sub
And then I would create a new connection object, did what I needed to do, and then closed the connection and destroyed the connection object. When I've done this before long ago in ADO with VB6, the process created by the connection was killed when the connection object was destroyed, but that doesn't appear to be the case anymore. Now every time I create a new connection object and connect to my server, a new process is created and then put to sleep when I close my connection. After a while the server will start refusing connections until I log in and kill all the processes my app created. Obviously this isn't being done right, and I would like to learn the right way.
Would it be better to simply pass the same connection object by reference (or inside a wrapper class) among my forms, leaving the connection object open?
What is the correct way to close my connection so that I don't eventually get a bunch of sleeping processes on my SQL server? Is there a setting in SQL server I can adjust to automatically kill processes after a certain period of inactivity?
Would you consider encrypting the password in runtime memory overkill?
Thank you for any help. :)