执行查询时如何获取主键值?

时间:2019-08-04 04:29:09

标签: sql vb.net

这是登录按钮代码和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

2 个答案:

答案 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