列表包含重复的人员

时间:2013-12-06 16:49:37

标签: vb.net

请参阅以下代码:

Public Function ExecuteDynamicQuery(ByVal strSQL As String, ByVal list As List(Of clsType), ByVal tyType As clsType) As List(Of clsType) Implements IGenie.ExecuteDynamicQuery
            Dim objParameterValues As New clsParameterValues
            Dim iConnectionBLL As iConnectionBLL
            Dim objCon As DbConnection
            Dim objDR As DbDataReader
            Dim paramValues() As DbParameter
            objParameterValues = New clsParameterValues
            iConnectionBLL = New clsConnectionBLL()
            objCon = iConnectionBLL.getDatabaseTypeByDescription("Genie2")
            Using objCon
                paramValues = objParameterValues.getParameterValues
                objDR = clsDatabaseHelper.ExecuteReader(objCon, CommandType.Text, strSQL, paramValues)
                Do While objDR.Read
                    Dim tyType2 As clsType = tyType
                    tyType.PopulateDataReader(objDR)
                    list.Add(tyType2)
                Loop
                objDR.Close()
                Return list
            End Using
        End Function

将SQL语句与clsType(基本类型)一起传递给函数。返回类型列表,例如人员名单。例如,在这种情况下,strSQL =“SELECT * FROM Persons”。返回500人的列表,但他们都是同一个人(最后一个人被添加到列表中)。我意识到这是因为列表为每个条目引用了相同的对象。我该如何改变?

2 个答案:

答案 0 :(得分:2)

这种情况下,使方法通用会很有用。例如:

Public Function MyGenericMethod(Of T As New)() As List(Of T)
    Dim results As New List(Of T)()
    For i As Integer = 0 To 9
        Dim item As New T()
        ' Populate item ...
        results.Add(item)
    Next
    Return results
End Function

但是,对于它的价值,我看到人们经常尝试做这种事情,而且我从不和我好好相处。我总是第一个建议公共代码应该被封装而不是重复的地方,但是,我从来没有被说服创建某种类型的数据访问层来封装对ADO的调用,但< em>不也封装SQL,是个好主意。

考虑一下ADO,它本身就是数据访问层那部分的封装。当然,它可能比执行一个简单的SQL命令要多几行代码,但这种额外的复杂性是有原因的。为了支持数据源的所有功能,这是必要的。如果您尝试简化它,不可避免地,您将来有一天需要使用数据源的其他功能,但您的简化界面将不支持它。在我看来,每个数据访问方法应该直接使用所有必需的ADO对象,而不是尝试创建一些常用方法来实现。是的,这确实意味着你的许多数据访问方法在结构上会非常相似,但我认为从长远来看你会更快乐。

答案 1 :(得分:1)

我减少了原始代码。以下示例在功能上等同于您发布的内容。如果不了解更多关于你的类型的内容,很难给你提供更多的东西,但是减少代码可能会使代码足够清晰,你可以找到解决方案:

Public Function ExecuteDynamicQuery(ByVal sql As String, ByVal list As List(Of clsType), ByVal type As clsType) As List(Of clsType) Implements IGenie.ExecuteDynamicQuery
    Dim paramValues() As DbParameter = New clsParameterValues().getParameterValues()
    Using conn As DbConnection = iConnectionBLL.getDatabaseTypeByDescription("Genie2"), _
          rdr  As DbDataReader = clsDatabaseHelper.ExecuteReader(conn, CommandType.Text, sql, paramValues)

        While rdr.Read()
            type.PopulateDataReader(rdr)
            list.Add(type)
        End While

        Return list
    End Using           
End Function

我可以给你一些额外的建议:

  1. 必须能够接受与查询本身分开的查询的参数信息。您调用的ExecuteReader()方法支持此方法,但您只传递一个空数组。解决此问题,或遭到入侵。
  2. 使用泛型的实现(如另一个答案中所述)将更简单,更清晰。您所依赖的Genie界面似乎没有增加太多价值。使用了解泛型的系统,你可能会做得更好。
  3. 通过在循环内创建一个新对象,可以解决一遍又一遍地重复使用同一个对象的问题。如上所述,唯一的方法是使用New clsType(并且看起来你可能有Option Strict Off,这样可能会在运行时爆炸),通过一些凌乱的反射代码,切换到使用#2中建议的泛型,或接受可以为您构建新对象的Func(Of clsType)委托。