将参数传递给来自多个不同事件的SQL Server插入查询

时间:2018-12-07 19:53:02

标签: vb.net winforms sql-server-2008 stored-procedures parameters

我正在Visual Studio 2013中编写具有多种形式的Winforms应用程序。我添加了一个事件日志,以查看谁在使用什么,登录时间,注销时间等(所有内容均无害,这是工作团队的管理工具)。我想简化并减少所需代码的长度。

现在,在所有表单上的每个“事件子”中都有以下代码。

 Dim connection As New SqlConnection("Server= server\instance; Database = db;
                                      User ID=uID;Password=pw")

 Private Sub btnAssociate_Click(sender As Object, e As EventArgs) Handles btnAssociate.Click
    Dim eLogCMD As New SqlCommand("sp_EventLog", connection)
    Me.connection.Open()
    eLogCMD.CommandType = CommandType.StoredProcedure
    eLogCMD.Parameters.AddWithValue("@Username", Login.UsernameTextBox.Text.ToString())
    eLogCMD.Parameters.AddWithValue("@Action", "AssociateArea")
    eLogCMD.Parameters.AddWithValue("@Comments", "Entered Associate Area")
    eLogCMD.ExecuteNonQuery()
    Me.connection.Close()

还有其他几个Sub,它们都具有相同的代码,并且具有相同的连接SqlCommand和声明的参数的多种形式;只有参数值改变。它有效,但是必须有一种更清洁的方法。

我想在主窗体上创建一个SqlConnectionSqlCommand,以从不同的窗体和事件子调用并传递参数。我正在寻找这样的简单东西:

Sub --Whatever Event
    Main.eLogCMD.ExecuteNonQuery(1stParameterValue, 2ndParameterValue, 3rdParameterValue)
End Sub

显示SQL Server存储过程:

CREATE PROCEDURE [dbo].[sp_EventLog]        
     @Username VARCHAR(50),
     @Action   VARCHAR(30),
     @Comments VARCHAR(100)     
AS       
BEGIN
    INSERT INTO AppEventLog ([Username], [Action], [Comments])
    VALUES (@Username, @Action, @Comments)      
END

1 个答案:

答案 0 :(得分:4)

请勿将此部分设为任何形式。相反,您可以将代码放入其自己的模块中。然后仅使用编写日志所需的参数在Module上调用方法。

请勿尝试在您的应用程序中重复使用相同的连接 object 。这将干扰ADO.Net中称为“连接池”的功能。您可以(并且应该)重复使用相同的连接字符串,但这是不同的。

Public Module Events 
    Private CnString As String = "Server= server\instance; Database = db; User ID=uID;Password=pw"

    Public Sub LogAction(User As String, ActionName As String, Comment As String)
        Using cn As New SqlConnection(CnString), _
              LogCmd As New SqlCommand("sp_EventLog", cn)

            LogCmd.CommandType = CommandType.StoredProcedure
            'AVOID ADDWITHVALUE()! It can cause significant performance problems
            'Instead, set these to match actual column types and lengths from the DB
            LogCmd.Parameters.Add("@Username", SqlDbType.NVarChar, 30).Value = User
            LogCmd.Parameters.Add("@Action", SqlDbType.NVarChar, 80).Value = ActionName
            LogCmd.Parameters.Add("@Comments", SqlDbType.NVarChar, 500).Value = Comment

            cn.Open()
            LogCMD.ExecuteNonQuery()
        End Using
    End Sub  
End Module

然后您现有的方法简化为使用此模式:

Private Sub btnAssociate_Click(sender As Object, e As EventArgs) Handles btnAssociate.Click
    Events.LogAction(Login.UsernameTextBox.Text, "AssociateArea", "Entered Associate Area")

    '...
End Sub

理想情况下,所有数据库访问将通过这样的模块运行,在该模块中,用户界面事件永远不会直接与数据库对话,而只会在您的数据库模块上调用方法。