2009-02-17 110 views
0

背景:我正在将使用MS Access进行数据存储的VB6应用程序改写为使用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 2010-01-14 15:54:07

回答

8

不应该表单之间传递连接对象。基本上,使用SQL Server连接时的模式是创建连接,打开连接,执行操作,然后关闭连接。

为此,你应该有一个公共静态方法的地方,这将产生你的SqlConnection,你会在使用语句中使用,就像这样:

Using connection As SqlConnection = GetConnection 
    ' Use connection here. 

End Using 

这应该避免的过程,从上堆放服务器。

+0

从来没有尝试过这种方式,但它比我脑海中的东西更有意义。我会给这个镜头,谢谢! – 2009-02-17 19:46:16

+0

假设你需要调用一个sub 100次,那么你需要在sub中打开100个连接。为了防止您需要更高级别的上下文来进行共享。否则,这很好。 – Middletone 2009-02-17 21:27:38

+0

@Middletone:我同意,但必须采取非常严格的步骤才能确保正确处理连接。只是有一个连接在一起是一个非常糟糕的主意。您应该创建连接,然后将其传递给执行迭代的例程。 – casperOne 2009-02-17 21:59:44

1

您可以使用Using语句,它将在完成时关闭并处理连接。

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

End Using 

如果你没有调用.Close(),那可能是问题所在。

1

我同意卡斯帕尔。如果您确实需要在页面之间共享对象以减少负载,那么您可以使用静态成员变量来执行此操作。只要确保在执行最后一条语句时关闭连接。您还可以创建一个连接作用域,可以在最后一个事务完成时处置。如果您没有这方面的经验,那么请尽早打开并关闭您的连接,并且不要通过它。

我有一个网络应用程序,并减少一些延迟有些情况下,我使用我为DAL创建的范围,以便如果在子功能中有调用,他们可以使用相同的连接,而不是晋升为MSDTC。然而,这实际上只在交易系统中是必需的。

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中,除非您需要灵活地使用不同的连接字符串打开多个连接。

相关问题