【发布时间】:2018-06-23 20:27:15
【问题描述】:
我无法准确理解为什么会发生这种情况。
(直到我从雇主那里获得 SQL 权限)我正在开发一个需要身份验证的程序,所以我使用的是 XML 文档,并使用 XDocument 实用程序读取它。一切都正确加载到用户集合中。该集合在名为“UserDatabaseManager”的类中定义为:
收藏:
Private UserCollection As New List(Of User)
UserCollection 的父级定义为:
Public UserDatabaseController As New UserDatabaseManager()
这是用户类:
Public Class User
'CONSTANTS ----------------------------
Public Enum RoleCode
BasicQAAgent = 0
QAAdministrator = 1
ITadmin = 5
End Enum
'VARIABLES ----------------------------
Dim uname As String = ""
Dim fname As String = ""
Dim pass As String = ""
Dim userrole As RoleCode = 0
Dim idnumber As Integer = 0
Dim createDate As String = ""
Shared Function SerializeUserFromXMLNode(ByVal XMLelement As XElement) As User
With XMLelement
Return New User(.@name, .<fullname>.Value, .<creationday>.Value, .<password>.Value, .<role>.Value)
End With
End Function
Public Sub New(ByVal Name As String, ByVal FullName As String, ByVal CreationDay As String, ByVal PassHash As String, ByVal Role As RoleCode)
fname = FullName : uname = Name : createDate = CreationDay : pass = PassHash : userrole = Role
End Sub
Public ReadOnly Property UserName As String
Get
Return uname
End Get
End Property
Public ReadOnly Property FullName As String
Get
Return fname
End Get
End Property
Public ReadOnly Property UserRoleCode As RoleCode
Get
Return userrole
End Get
End Property
Public ReadOnly Property UserIDNumber As Integer
Get
Return idnumber
End Get
End Property
Public ReadOnly Property PasswordMD5Hash As String
Get
Return pass
End Get
End Property
Public ReadOnly Property CreationDate As Date
Get
Return createDate
End Get
End Property
End Class
我创建了自己的用户。断点确认 我的用户 以及所有其他记录都已从 XDocument 成功加载。我能做到:
UserCollection.Item(0)
我的用户类将被返回(我知道我在 xdocument 中的索引为 0)。
现在。如果我想使用其他字段搜索用户怎么办?
我在用户数据库管理器类(用户集合的父类、用户类和 XDocument 工具)中有一个函数,它通过用户,找到与名称匹配的用户,并返回用户的实例到函数的调用:
Public Function GetUserByName(ByVal name As String) As User
For Each usr As User In UserCollection
If usr.UserName = name Then
Return usr
End If
Next
Return Nothing
End Function
总是没有返回,事实上,“If usr.Username...”上的断点确认 ForEach 语句甚至没有运行循环!
所以基本上最终结果是来自登录屏幕的 NullObjectReference。以下是在登录屏幕表单中调用 GetUserByName 的代码:
Private Sub Btn_login_Click(sender As Object, e As EventArgs) Handles btn_login.Click
DisableLoginElements() 'custom sub
'try login
'Try
Dim inputUsr As String = tbox_Username.Text : Dim inputPass As String = CalculateMD5FromString(tbox_Password.Text)
tbox_Password.Clear()
If mainMDI.UserDatabaseController.GetUserByName(inputUsr) IsNot Nothing Then 'HIGHTODO: FIX NULLOBJECTREF FROM USER SEARCH.
'crosscheck the password provided calculates same MD5 hash as MD5 hash stored in DB. if not, throw MD5calculationVarianceEx Exception
If mainMDI.UserDatabaseController.GetUserByName(inputUsr).PasswordMD5Hash = inputPass Then
mainMDI.initializeMainMDIwithUser(mainMDI.UserDatabaseController.GetUserByName(inputUsr)) 'authentication success!
Else
Throw MD5calculationVarianceEx 'Password does not match
End If
Else
Throw UserNotFoundEx 'user was not found
End If
'Catch ex As Exception 'an error occured, determine error
'MsgBox(ex.Message, MsgBoxStyle.Critical, "Login Error: QA Commander")
'EnableLoginElements()
'End Try
End Sub
您看到 HIGHTODO 注释的地方是没有返回任何内容的地方。出于调试目的,我注释掉了 Try 语句。
请帮助我在“T”代表的对象内的属性列表中搜索!
编辑:这里是 XML 和 UserDatabaseManager 的完整副本:
用户数据库管理器:
Imports System.Collections.ObjectModel
Imports Microsoft
Public Class UserDatabaseManager
Public ReadOnly UserDatabaseManagerVersion As String = "1.0"
Private ReadOnly DBManager As Integer 'User ID Number of the database administrator
Private Company As String
Private Department As String
Private UserCollectionIndex As New Specialized.StringCollection
Public UserCollection As New List(Of User)
Dim xmlMgr As XDocument
Public Sub New(ByVal Optional databaseXMLPath As String = "")
If Not databaseXMLPath = "" Then
'Load datasheet from location
xmlMgr = XDocument.Load(databaseXMLPath)
If Not xmlMgr.<UserDB>.<version>.@value = UserDatabaseManagerVersion Then 'User Database is outdated.
Throw UserDBfileVersionMismatchEX
End If
DBManager = xmlMgr.<UserDB>.<dbAdministrator>.@value
Company = xmlMgr.<UserDB>.<company>.@value
Department = xmlMgr.<UserDB>.<department>.@value
Dim usersInDB As IEnumerable(Of XElement) = xmlMgr.Descendants("user")
For Each elm As XElement In usersInDB
Dim foundName As String = elm.@name
Dim userEntry As UserDatabaseManager.User = New User(elm.@name, elm.<fullname>.Value, elm.<creationdate>.Value,
elm.<password>.Value, elm.<role>.Value)
UserCollection.Add(User.SerializeUserFromXMLNode(elm))
Next
Else
'create empty instance
End If
'get metadeta from XDocument
End Sub
Public Function GetUserByName(ByVal name As String) As User
For Each usr As User In UserCollection
If usr.UserName = name Then
Return usr
End If
Next
Return Nothing
End Function
Private Function GetUserByID(ByVal ID As Integer) As User
For Each usr As User In UserCollection
If usr.UserIDNumber = ID Then
Return usr : Exit Function
End If
Next
Return Nothing
End Function
Public Class User
'CONSTANTS ----------------------------
Public Enum RoleCode
BasicQAAgent = 0
QAAdministrator = 1
ITadmin = 5
End Enum
'VARIABLES ----------------------------
Dim uname As String = ""
Dim fname As String = ""
Dim pass As String = ""
Dim userrole As RoleCode = 0
Dim idnumber As Integer = 0
Dim createDate As String = ""
Shared Function SerializeUserFromXMLNode(ByVal XMLelement As XElement) As User
With XMLelement
Return New User(.@name, .<fullname>.Value, .<creationday>.Value, .<password>.Value, .<role>.Value)
End With
End Function
Public Sub New(ByVal Name As String, ByVal FullName As String, ByVal CreationDay As String, ByVal PassHash As String, ByVal Role As RoleCode)
fname = FullName : uname = Name : createDate = CreationDay : pass = PassHash : userrole = Role
End Sub
Public ReadOnly Property UserName As String
Get
Return uname
End Get
End Property
Public ReadOnly Property FullName As String
Get
Return fname
End Get
End Property
Public ReadOnly Property UserRoleCode As RoleCode
Get
Return userrole
End Get
End Property
Public ReadOnly Property UserIDNumber As Integer
Get
Return idnumber
End Get
End Property
Public ReadOnly Property PasswordMD5Hash As String
Get
Return pass
End Get
End Property
Public ReadOnly Property CreationDate As Date
Get
Return createDate
End Get
End Property
End Class
数据库 XML:
<UserDB>
<version value="1.0" />
<lastEditedDate value="6/21/2018 3:23PM" />
<dbAdministrator value="0000001" />
<company value="Anomaly Squared" />
<department value ="Quality Assurance" />
<DBPreferences>
<DefaultPassword>Password18</DefaultPassword>
<DefaultPasswordHash>E527FABE14F0F6C0C7AD35886614BEAE</DefaultPasswordHash>
<ForcePassChangeIfDefault>True</ForcePassChangeIfDefault>
</DBPreferences>
<QAAgents>
<user name="mwendel">
<userid>0000001</userid>
<password>8814CD66C7804638B4CCE9233CBF4987</password>
<fullname>Matthew Wendel</fullname>
<role>5</role>
<creationdate>6/23/2018</creationdate>
<activityHistory>
<action kind="selfCreatedAccount" date="6/23/2018" result="0x0" />
</activityHistory>
</user>
<user name="jappleseed">
<userid>0185432</userid>
<password>E527FABE14F0F6C0C7AD35886614BEAE</password>
<fullname>Johnny Appleseed</fullname>
<role>1</role>
<creationdate>6/23/2018</creationdate>
<activityHistory>
<result kind="ITCreatedAccount" date="6/23/2018" result="0x0" />
</activityHistory>
</user>
</QAAgents>
</UserDB>
用户角色定义
0 = 基本 QA 代理。
有能力:
• 创建新的评估
• 查看已完成的评估
• 添加员工
1 = QA 管理员
与基本相同,但另外:
• 添加/创建 QA 代理帐户。
• 可以编辑以前的评估。
• 对基本 QA 代理进行评估
• 添加/编辑/删除活动
5 = IT/系统管理员
完全自主地编辑和维护系统的所有元素。
【问题讨论】:
-
你能发布你的xml文件吗?
-
另外,你能不能把UserDatabaseManager的属性也贴出来
-
感谢您的快速回复!我用我的代码对问题进行了编辑,并为 XML 提供了指向 PasteBin 的链接。
-
别担心,我会检查一下,看看我能做什么
-
我无法用
UserDatabaseManager类重现您的问题。但是,我强烈建议您启用 Option Strict 并修复 IDE 发现的问题。
标签: vb.net loops for-loop foreach