Vb.net 将参数从多个不同事件传递到SQL Server insert查询
我正在Visual Studio 2013中编写一个Winforms应用程序,它有多个表单。我正在添加一个事件日志,以查看谁在使用什么、登录时间、注销时间等(这些都是无害的,这是工作团队的管理工具)。我想简化和减少所需的代码长度 现在我在所有表单的每个事件子项中都有以下代码Vb.net 将参数从多个不同事件传递到SQL Server insert查询,vb.net,winforms,sql-server-2008,stored-procedures,parameters,Vb.net,Winforms,Sql Server 2008,Stored Procedures,Parameters,我正在Visual Studio 2013中编写一个Winforms应用程序,它有多个表单。我正在添加一个事件日志,以查看谁在使用什么、登录时间、注销时间等(这些都是无害的,这是工作团队的管理工具)。我想简化和减少所需的代码长度 现在我在所有表单的每个事件子项中都有以下代码 Dim connection As New SqlConnection("Server= server\instance; Database = db;
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,所有sub都具有相同的代码,多个表单具有相同的连接,SqlCommand
,并且声明了参数;只有参数值会更改。这是可行的,但必须有更干净的方法
我想在主窗体上创建一个SqlConnection
和SqlCommand
,从不同的窗体和事件子窗体调用和传递参数。我在找这样简单的东西:
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
不要把这部分做成任何形式。相反,您可以将代码放在它自己的模块中。然后在模块上调用一个方法,该方法只包含写入日志所需的参数 不要试图在应用程序中重复使用相同的连接对象。这将干扰ADO.Net中称为连接池的功能。您可以(也应该)重复使用相同的连接字符串,但这是不同的
公共模块事件
Private CnString As String=“Server=Server\instance;Database=db;User ID=uID;Password=pw”
公共子日志操作(用户作为字符串,操作名作为字符串,注释作为字符串)
将cn用作新的SqlConnection(CnString)_
LogCmd作为新的SqlCommand(“sp_EventLog”,cn)
LogCmd.CommandType=CommandType.StoredProcess
'避免使用ADDWITHVALUE()!它可能会导致严重的性能问题
'相反,将其设置为与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()
终端使用
端接头
端模块
然后,您现有的方法将简化为使用此模式:
Private Sub btnasociate\u单击(发送者作为对象,e作为事件参数)处理btnasociate。单击
Events.LogAction(Login.UsernameTextBox.Text,“AssociateArea”,“已进入关联区域”)
'...
端接头
理想情况下,ALL数据库访问将通过这样一个模块运行,其中用户界面事件从不直接与数据库对话,而是只调用数据库模块上的方法。不要将此部分作为任何形式。相反,您可以将代码放在它自己的模块中。然后在模块上调用一个方法,该方法只包含写入日志所需的参数 不要试图在应用程序中重复使用相同的连接对象。这将干扰ADO.Net中称为连接池的功能。您可以(也应该)重复使用相同的连接字符串,但这是不同的
公共模块事件
Private CnString As String=“Server=Server\instance;Database=db;User ID=uID;Password=pw”
公共子日志操作(用户作为字符串,操作名作为字符串,注释作为字符串)
将cn用作新的SqlConnection(CnString)_
LogCmd作为新的SqlCommand(“sp_EventLog”,cn)
LogCmd.CommandType=CommandType.StoredProcess
'避免使用ADDWITHVALUE()!它可能会导致严重的性能问题
'相反,将其设置为与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()
终端使用
端接头
端模块
然后,您现有的方法将简化为使用此模式:
Private Sub btnasociate\u单击(发送者作为对象,e作为事件参数)处理btnasociate。单击
Events.LogAction(Login.UsernameTextBox.Text,“AssociateArea”,“已进入关联区域”)
'...
端接头
理想情况下,所有数据库访问都将通过这样的模块运行,用户界面事件从不直接与数据库对话,而是只调用数据库模块上的方法。是否有原因不能将该逻辑移动到共享模块?旁注:不应在存储过程中使用
sp
前缀。微软已经这样做了,而且你确实有可能在将来的某个时候发生名称冲突。最好只是简单地避免使用sp.
并使用其他东西作为前缀,或者根本不使用前缀@很抱歉,我还没有找到任何可以帮助我的东西,我是一个新手VB@marc_s谢谢,我会改变的。没问题,我只是好奇你是否已经考虑过了,并且因为某种原因决定它不起作用。无论如何,Joel写了一个很好的例子,这是处理问题的正确方法。如果你还是VB新手,如果有部分你不理解,请毫不犹豫地询问他的答案。祝你好运是否存在无法将该逻辑移动到共享模块的原因?旁注:您不应在存储过程中使用sp\uu
前缀。微软已经这样做了,而且你确实有可能在将来的某个时候发生名称冲突。最好只是简单地避免使用sp.
并使用其他东西作为前缀,或者根本不使用前缀@很抱歉,我还没有找到任何可以帮助我的东西,我是一个新手VB@marc_s谢谢,我会改变的。没问题,我只是好奇你是否已经考虑过了,并且因为某种原因决定它不起作用。无论如何,Joel写了一个很好的例子,这是处理问题的正确方法