这是登录按钮代码和EditUser()
功能:
Private Sub BtnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
If (isformvalid()) Then
qr = "Select * from userlogin where UserName='" & txtUser.Text & "' and Password='" & txtPassword.Text & "' and UserType ='" & ComboBox1.Text & "' "
ds = searchdata(qr)
If (ds.Tables(0).Rows.Count > 0) Then
LoginUser = txtUser.Text
LoginPass = txtPassword.Text
UserType = ComboBox1.Text
EditUser()
Dashbord.Show()
Me.Close()
Else
MsgBox("UserName or Password is Incorrect. Please Cheak And Try Again")
txtUser.ResetText()
txtPassword.ResetText()
End If
End If
End Sub
Private Function EditUser()
If (isformvalid()) Then
q = "Insert into UserLoginAudit (UserName, Password, UserType, ActivityLogin) Values('" & txtUser.Text & "','" & txtPassword.Text & "','" & ComboBox1.Text & "','" & DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") & "')"
ProID = lastProID(q)
End If
End Function
这是模块代码:
Module DBSQLServer
Public con As New SqlConnection("Data Source=JOYALXDESKTOP\SQLEXPRESS;Initial Catalog=SaleInventory;Integrated Security=True")
Public cmd As New SqlCommand
Public da As New SqlDataAdapter
Public ds As New DataSet
Public dt As DataTable
Public qr As String
Public i As Integer
Public newProID As Integer
Public Function searchdata(ByVal qr As String) As DataSet
da = New SqlDataAdapter(qr, con)
ds = New DataSet
da.Fill(ds)
Return ds
End Function
Public Function insertdata(ByVal qr As String) As Integer
cmd = New SqlCommand(qr, con)
con.Open()
i = cmd.ExecuteNonQuery()
con.Close()
Return i
End Function
Public Function lastProID(ByVal qr As String) As Integer
cmd = New SqlCommand(qr, con)
con.Open()
newProID = cmd.ExecuteScalar
con.Close()
Return newProID
End Function
End Module
这是我的注销代码和EditUser()
函数:
Private Sub Label1_Click_1(sender As Object, e As EventArgs) Handles Label1.Click
Application.Exit()
EditUser()
End Sub
Private Function EditUser()
q0 = "UPDATE UserLoginAudit SET ActivityOffline = '" & DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") & "' WHERE AuditID = '" & My.Forms.login.ProID & "';"
Dim logincorrect As Boolean = Convert.ToBoolean(insertdata(q0))
If (logincorrect) Then
MsgBox("LogOut Successful ...", MsgBoxStyle.Information)
Else
MsgBox("Something Wrong. LogOut Failed. Please Check and Try Again...", MsgBoxStyle.Critical)
End If
End Function
当我运行程序时,单击登录按钮后,数据(用户名,密码,用户类型,活动登录)将完美插入。
但是当我单击数据库ActivityOffline
中的“注销”按钮时,列值仍然为空。
然后,我创建一个表单加载事件,以检查创建注销按钮的主表单中ProID的值:
Private Sub Dashbord_Load(sender As Object, e As EventArgs) Handles MyBase.Load
hi.Text = My.Forms.login.ProID
End Sub
它总是显示0
答案 0 :(得分:1)
这里有一个很多,因此请花一些时间通读并理解所有更改...因为其中一些看似微不足道的内容实际上非常重要:
Module DBSQLServer
'Don't try to re-use the connection object. It interferes with connection pooling and makes things worse, rather than better
'Instead, just re-use the connection string
Private ConnectionString As String = "Connection String here"
'Make this private. Then have a public method for each actual query you use
'It will force you to create a cleaner separation between DB and UI
'If this starts to make for a really huge module, move this to a separate class library, where the public methods are divided up into separate modules for logical groupings and the private methods are in a common Friend module using the InternalsVisibleTo attribute
Private Function searchdata(sql As String, ParamArray data() As SqlParameter) As DataSet
Dim result As New DataSet()
Using cn As New SqlConnection(ConnectionString), _
cmd As New SqlCommand(sql, cn), _
da As New SqlDataAdapter(cmd)
If data IsNot Nothing Then
For Each parameter As SqlParameter In data
cmd.Parameters.Add(parameter)
Next
End If
da.Fill(result)
End Using
Return result
End Function
' This may need some work yet
Private Function GetValue(Of T)(ByVal qr As String, ParamArray data() As SqlParameter) As T
Using cn As New SqlConnection(ConnectionString), _
cmd = New SqlCommand(qr, con)
If data IsNot Nothing Then
For Each parameter As SqlParameter In data
cmd.Parameters.Add(parameter)
Next
End If
con.Open()
' To do: better handling for NULL
Return CType(cmd.ExecuteScalar(), T)
End Using
End Function
'Now the Public methods
Public Function ValidateCredentials(Username As String, HashedPassword As String, UserType As String) As Integer
Dim qr As String = "Select * from userlogin where UserName= @Username and Password= @Password and UserType = @UserType"
'Match the parameter declarations to the database column types and lengths
Dim u As New SqlParameter("@Username", SqlDbType.NVarChar, 20)
u.Value = UserName
'Thanks to hashing, this will be a fixed length
Dim p As New SqlParameter("@Password", SqlDbType.NChar, 60)
p.Value = HashedPassword
Dim t As New SqlParameter("@UserType", SqlDbType.VarChar, 10)
t.Value = UserType
Dim ds As DataSet = searchdata(qr, u, p, t)
If ds.Tables(0).Rows.Count > 0 Then
' Moving this call here, as part of ValidateCredentials, prevents
' any possibility of logging in without also creating an audit
Return CreateUserLoginAuditRecord(Username, Password, UserType)
Else
Return -1
End If
End Function
' Logging Passwords is also a **HUGE** no-no. Please remove that field from your audit table
Public Function CreateUserLoginAuditRecord(Username As String, Password As String, Usertype As String)
'Even better to combine this with the Validate query, as one long sql string handling multiple statements.
Dim qr As String = "Insert into UserLoginAudit (UserName, Password, UserType, ActivityLogin) Values(@UserName, @Password, @UserType, current_timestamp);Select scope_identity;"
Dim u As New SqlParameter("@Username", SqlDbType.NVarChar, 20)
u.Value = UserName
Dim p As New SqlParameter("@Password", SqlDbType.NChar, 60)
p.Value = Password
Dim t As New SqlParameter("@UserType", SqlDbType.VarChar, 10)
t.Value = UserType
Return GetValue(Of Integer)(qr, u, p, t)
End Function
Public Function CloseUserLoginAuditRecord(AuditID As Integer) As Boolean
Dim qr As String = "UPDATE UserLoginAudit SET ActivityOffline = current_timestamp WHERE AuditID = @AuditID"
Dim a As New SqlParameter("@AuditID", SqlDbType.Integer)
a.Value = AuditID
Return GetValue(Of Boolean)(qr, a)
End Function
End Module
Public Function HashPassword(plainText As String) As String
'Leaving this for you. Read up on BCrypt.
'THIS IS IMPORTANT!!!!1!!
Throw New NotImplementedException()
End Function
Private Sub BtnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
If isformvalid() Then
Dim AuditID As Integer = DBSQLServer.ValidateCredentials(txtUser.Text, HashPassword(txtPassword.Text), ComboBox1.Text)
If (AuditID <> -1) Then
'Create ProID as a public property of the Dashboard class
Dashboard.ProID = AuditID
Dashboard.Show()
Me.Close()
Else
MsgBox("UserName or Password is Incorrect. Please Check And Try Again")
txtUser.ResetText()
txtPassword.ResetText()
End If
End If
End Sub
Private Sub Label1_Click_1(sender As Object, e As EventArgs) Handles Label1.Click
' This should really be handled by the form-closing event or similar.
' Event that won't be enough. You can't stop task manager, power failures, OS/application crashes, etc.
' No matter what, you **WILL** end up with a **LOT** of unresolved audits
' Really, it's best just to throw up your hands about this.
' Close what you can, but don't worry about the unclosed audit records, because you really can't stop that...
' ... in which case, you might just remove the MsbBox calls.
If DBSQLServer.CloseUserAuditLoginRecord(ProID) Then
MsgBox("LogOut Successful ...", MsgBoxStyle.Information)
Else
MsgBox("Something went wrong. LogOut Failed. Please Check and Try Again...", MsgBoxStyle.Critical)
End If
Application.Exit()
End Sub
答案 1 :(得分:0)
在Insert语句的末尾添加一个分号,以指示命令的结尾。然后添加
SELECT SCOPE_IDENTITY();
然后可以使用.ExecuteScalar并期望返回新的主键。
但是
输出 这是Microsoft获得价值的首选方式,从我阅读的内容来看,他们无意在将来解决@@ identity和scope_Identity的任何问题,因为他们认为OUTPUT可以替代。
CREATE PROCEDURE [Sales].[uspNewCustomer]
@CustomerName NVARCHAR (40),
@CustomerID INT OUTPUT
AS
BEGIN
INSERT INTO [Sales].[Customer] (CustomerName) VALUES (@CustomerName);
SET @CustomerID = SCOPE_IDENTITY();
RETURN @@ERROR
END