【问题标题】:Get and setter in VB.NET在 VB.NET 中获取和设置
【发布时间】:2013-02-28 20:40:23
【问题描述】:

我觉得在这里提出这个问题非常困难,因为我认为我无法为这个社区提供任何回报。 我目前正在编写一个应用程序,一旦启动,它就会要求用户登录.如果用户输入的数据与数据库中的数据匹配,则用户已登录。然后应用程序从数据库中获取有关用户的数据,例如用户 ID、姓名、角色。

现在我希望这些信息能在应用程序中广泛使用。我现在的情况:

  • 解决方案
    • 可执行文件(主项目)
    • Database.dll(类等)

在 database.dll 中我有以下类:

Public Class SessionProfile
Public _gebruikersID As String
Public _gebruikersNaam As String
Public _gebruikersRole As String

Public Property gebruikersID() As String
    Get
        Return _gebruikersID
    End Get

    Set(ByVal value As String)
        _gebruikersID = value
    End Set
End Property

Public Property gebruikersNaam() As String
    Get
        Return _gebruikersNaam
    End Get

    Set(ByVal value As String)
        _gebruikersNaam = value
    End Set
End Property

Public Property gebruikersRole() As String
    Get
        Return _gebruikersRole
    End Get

    Set(ByVal value As String)
        _gebruikersRole = value
    End Set
End Property
End Class

在我的主要可执行文件中,我将此类称为如下:Dim SessionProfile As New Database.SessionProfile(),在我的登录表单中,我使用以下代码设置设置器:

If loginResult = 1 Then
     SessionProfile.gebruikersID = SQLHook.Results("SELECT * FROM tblgebruikers WHERE GebruikersNaam = '" & TextGebruikersNaam.Text.Replace("'", "''") & "'", "GebruikersID")
     SessionProfile.gebruikersNaam = SQLHook.Results("SELECT * FROM tblgebruikers WHERE GebruikersNaam = '" & TextGebruikersNaam.Text.Replace("'", "''") & "'", "gebruikersNaam")
     SessionProfile.gebruikersRole = SQLHook.Results("SELECT * FROM tblgebruikers WHERE GebruikersNaam = '" & TextGebruikersNaam.Text.Replace("'", "''") & "'", "gebruikersRole")
     DialogResult = DialogResult.OK
Else
     SessionProfile.gebruikersID = ""
     SessionProfile.gebruikersNaam = ""
     SessionProfile.gebruikersRole = ""
     DialogResult = DialogResult.NO
End If

现在我回到我的主窗体并使用例如MsgBox(SessionProfile.GebruikersNaam),但我没有得到任何返回。

这个理论不起作用是有原因的还是我做错了什么?查询很好,因为如果您将它们调暗为字符串并将它们添加到 msgbox 中,它会显示正确的文本。

有人可以帮我解决我的问题吗?

【问题讨论】:

  • 您在主可执行文件中声明了一个名为“SessionProfile”的变量,您能否告诉我该变量是否传递给您设置属性的登录表单,或者您是否声明了一个新的(和不同的) 一个?
  • @Steve 在主可执行文件中,我有两个名为“frmMain”和“frmLogin”的表单,并且在这两种表单中都声明了此代码。

标签: vb.net


【解决方案1】:

如果我正确理解您的情况,您属于以下情况。

在主可执行文件中,您在某处声明了一个变量(我将更改名称以便更好地解释)

Dim currProfile As New Database.SessionProfile() 

这意味着你已经创建了一个 SessionProfile 类型的变量,现在你调用了 frmLogin

Dim form1 As new frmLogin()
if DialogResult.OK = form1.ShowDialog() then
    MsgBox(curProfile.GebruikersNaam) ' shows nothing'

在 frmLogin 中你声明了一个新的(不同的)变量

Dim profile As New Database.SessionProfile()

这个变量是一个不同的变量,与主窗体中声明的变量没有任何共享,设置它的属性并不意味着另一个 SessionProfile 变量看到这些变化。
您需要将第一个变量传递给 frmLogin。也许在构造函数中。

Dim form1 As new frmLogin(currProfile)
if DialogResult.OK = form1.ShowDialog() then
    MsgBox(curProfile.GebruikersNaam) ' shows the name'

并在frmLogin构造函数中接收并存储传入的变量

Dim profile As SessionProfile = Nothing
Public Sub New(ByVal p As SessionProfile)
    profile = p
    InitializeComponent()
End Sub

现在,当您在内部 (frmLogin) 配置文件变量上设置属性时,您正在设置主窗体中使用的同一实例的属性。
顺便说一句,避免用你的类的同名来调用你的变量。真的很迷茫

【讨论】:

  • 我理解你的代码 80% 并尝试在我的代码中实现这一点,我知道如何“解决问题”。现在在Public Sub New(ByVal p As SessionProfile) 我收到以下错误在设计器生成的类型'frmLogin' 中应该调用InitializeComponent 方法。我不知道这意味着什么?我很抱歉。
  • 好吧,InitializeComponent 是 Visual Studio IDE 为您编写的一种方法,它声明和初始化表单中存在的每个 TextBox、Button、DataGrid 等。当您声明一个显式的 New 构造函数时,您应该调用此方法(我忘记在我的答案中写它)。请阅读 this article 关于 Forms 构造函数的内容,它有点冗长,但涵盖了基本内容。
  • 谢谢史蒂夫。我按照说明阅读了您引用的文章(确实有点冗长,但我从中得到了一个小想法)。现在,当我插入您的所有代码时,我在“frmLogin”中收到以下错误:'profile' is already declared as 'Private profile As Database.SessionProfile' in this class.。很抱歉,我对我的代码感到如此痛苦。
  • 不能说,只是搜索你的代码profile的第二个声明在哪里。
  • 它在代码中被双重引用。它现在正在工作。感谢史蒂夫的所有帮助。我今天确实学到了一些东西。
【解决方案2】:

您发布的代码似乎没有任何问题,可以解释您面临的问题,因此您可能希望将代码发布在您的主表单和登录表单上,以便我们查看看看发生了什么。

但是,如果您有时间进行快速代码审查,我建议您将本地字段的范围限定为类私有,因为您通过公共属性公开它们。这将有助于“保护”字段中的数据免受外部来源修改数据的影响,而无需访问您的设置器。

所以这个:

Public Class SessionProfile
Public _gebruikersID As String
Public _gebruikersNaam As String
Public _gebruikersRole As String

Public Property gebruikersID() As String
    Get
        Return _gebruikersID
    End Get

    Set(ByVal value As String)
        _gebruikersID = value
    End Set
End Property ...

应该是这样的:

Public Class SessionProfile
'Limit the scope to be private to the class;
private _gebruikersID As String
private _gebruikersNaam As String
private _gebruikersRole As String

Public Property gebruikersID() As String
    Get
        Return _gebruikersID
    End Get

    Set(ByVal value As String)
        _gebruikersID = value
    End Set
End Property ...

其次,也许更重要的是,您应该真正使用parameterized sql statements,而不是用户输入文本的字符串连接。我知道您正在使用已安装的应用程序,但仍然是一个很好的做法。

这些建议都不能帮助您解决最初的问题,因此请务必在相关表单上发布有关代码的更多详细信息,以便我们解决手头的问题。

【讨论】:

  • 我很抱歉。我应该为这个问题提供更多代码。由于它是一些巨大的代码行,我将它们发布在 Pastebin 上。 SessionProfile: http://pastebin.com/07ZBVrWMfrmMain: http://pastebin.com/qDkN9HbUfrmLogin: http://pastebin.com/kRTkyRJF
  • @Ruvvy 没问题,可能很难知道是什么代码导致了问题,因此选择要发布的代码可能会很棘手; )。查看您的代码后,我认为您会发现史蒂夫的回答非常有帮助。
  • 谢谢。我会从史蒂夫的回答中得到一个高峰。
【解决方案3】:

如果一次只能返回一个值,您的数据库查询似乎过于笼统。您只需进行一次查询即可获取所需的所有数据:

Dim sp As SessionProfile = Nothing

If loginResult = 1 Then
    Dim sqlConnStr = "your sql connection string"

    Dim nResults As Integer = 0
    Using sqlConn = New SqlConnection(sqlConnStr)

        ' N.B. always select only what you need, and always select explicitly
        Dim sql = "SELECT GebruikersID, gebruikersNaam, gebruikersRole FROM tblgebruikers WHERE GebruikersNaam = @Naam"

        Dim sqlCmd = New SqlCommand(sql, sqlConn)
        sqlCmd.Parameters.AddWithValue("@Naam", TextGebruikersNaam.Text)

        sqlConn.Open()

        Dim rdr = sqlCmd.ExecuteReader
        While rdr.Read
            sp = New SessionProfile With {.gebruikersID = rdr.GetString(0), _
                                          .gebruikersNaam = rdr.GetString(1), _
                                          .gebruikersRole = rdr.GetString(2)}

            nResults += 1
        End While

    End Using

    If nResults <> 1 Then
        Throw New Exception(String.Format("User {0} is in database more than once.", TextGebruikersNaam.Text))
    End If

    If sp IsNot Nothing Then
        ' sp now contains the session profile
    End If

End If

通过使用 SQL 参数,您无需对撇号等字符进行特殊处理 - 请注意该代码如何不使用 .Replace("'", "''")。

【讨论】:

  • 感谢您的建议。我的 MySQL 包装类是迈向好的一小步。如果您愿意,可以收到一份副本,以检查我开发这样的课程有多糟糕。
猜你喜欢
  • 2017-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多