集合列表清空自身

如何解决集合列表清空自身

我有一个类,用于向继承 System.Collections.CollectionBase 的数据库 (PostgreSQL) 连接对象添加参数。此类位于我用于多个应用程序的公共库中。通常,它会毫无问题地添加对象,但我开始遇到一个奇怪的问题,即集合无缘无故地清空其对象。这会导致 SQL 语句未正确构建的错误。


环境

  • Windows 10 专业版 x64 (19042.804)
  • Visual Studio 2017 CE (4.8.0484)
  • .NET Framework 4.7.2(库和应用程序)
  • PostgreSQL 服务器 v12.1
  • Npgsql 5.0.3(见下文

故障排除

这是发生问题的(混淆)代码:

SQLCommand = "INSERT INTO table" & vbCrLf
SQLCommand += "(" & vbCrLf
SQLCommand += vbTab & "column1," & vbCrLf
SQLCommand += vbTab & "column2," & vbCrLf
SQLCommand += vbTab & "column3," & vbCrLf
SQLCommand += vbTab & "column4," & vbCrLf
SQLCommand += vbTab & "column5," & vbCrLf
SQLCommand += vbTab & "column6," & vbCrLf
SQLCommand += vbTab & "column7," & vbCrLf
SQLCommand += vbTab & "column8," & vbCrLf
SQLCommand += vbTab & "column9," & vbCrLf
SQLCommand += vbTab & "column10" & vbCrLf
SQLCommand += ")" & vbCrLf
SQLCommand += "VALUES" & vbCrLf
SQLCommand += "(" & vbCrLf
SQLCommand += vbTab & ":parameter1," & vbCrLf
SQLCommand += vbTab & ":parameter2," & vbCrLf
SQLCommand += vbTab & ":parameter3," & vbCrLf
SQLCommand += vbTab & ":parameter4," & vbCrLf
SQLCommand += vbTab & ":parameter5," & vbCrLf
SQLCommand += vbTab & ":parameter6," & vbCrLf
SQLCommand += vbTab & ":parameter7," & vbCrLf
SQLCommand += vbTab & ":parameter8," & vbCrLf
SQLCommand += vbTab & ":parameter9," & vbCrLf
SQLCommand += vbTab & ":parameter10" & vbCrLf
SQLCommand += ")" & vbCrLf
SQLCommand += "RETURNING pkid"

PGDB.Parameters.Add(":parameter1",value1) 'String
PGDB.Parameters.Add(":parameter2",value2) 'String
PGDB.Parameters.Add(":parameter3",value3) 'String
PGDB.Parameters.Add(":parameter4",value4) 'String
PGDB.Parameters.Add(":parameter5",value5) 'String
PGDB.Parameters.Add(":parameter6",value6) 'String
PGDB.Parameters.Add(":parameter7",value7) 'String - THIS IS WHERE THE LIST CLEARS
PGDB.Parameters.Add(":parameter8",value8) 'Boolean
PGDB.Parameters.Add(":parameter9",value9) 'String
PGDB.Parameters.Add(":parameter10",value10) 'String

MyID = Convert.ToInt32(PGDB.ExecuteStatementScalar(SQLCommand))

PGDB 对象是我的 Npgsql 数据库连接对象,Parameters 对象是继承的集合。前六个参数添加到集合中没有问题,但是一旦添加第七个参数,整个列表就会清空自己并重新开始。正在执行的 SQL 语句应该如下所示:

-- EXPECTED SQL - WHAT IS STORED IN THE SQLCommand VARIABLE
INSERT INTO table
(
    column1,column2,column3,column4,column5,column6,column7,column8,column9,column10
)
VALUES
(
    :parameter1,:parameter2,:parameter3,:parameter4,:parameter5,:parameter6,:parameter7,:parameter8,:parameter9,:parameter10
)
RETURNING pkid

...但是,我得到的是:

-- ACTUAL (WRONG) SQL EXECUTED BY THE DATABASE
INSERT INTO table
(
    column1,$1,$2,$3,$4
)
RETURNING pkid

...然后在它实际尝试执行 SQL 语句时生成一个 Npgsql.PostgresException 抱怨语法:

42601: syntax error at or near ":"

我已经设置了断点来逐步完成该过程,但它始终是相同的行为。以下是我的 IDE 中的一些屏幕截图:

这是在添加第一个参数之前 Parameters 集合对象的样子:

Before First Parameter Added

这里是添加了第六个参数之后:

After Sixth Parameter Added

这是当它进入对第七个参数的 Add() 方法的执行时的样子:

Adding Seventh Parameter

可以肯定的是,我还检查了第六个参数上 Add() 方法进入执行时的状态:

Adding Sixth Parameter

这种方法一次运行没有错误,所以我不确定为什么它“突然”停止工作。为了解决此问题并使所有参数正确加载,我将 Npgsql 库从版本 4.1.8 升级到 5.0.3。在我与它斗争了一段时间后 - 我不得不解决与 System.Buffers 库的一些版本冲突 - 我能够让它再次运行,但不幸的是,我得到了完全相同的结果.

以防万一它可能是内存问题,我继续关闭所有东西并重新启动计算机。这也没有解决问题。

作为参考,这里是 PGSQLParameters 类的精简版本,不包括不同值类型的各种重载。

Imports Npgsql

#Region "POSTGRESQL PARAMETER COLLECTION OBJECT"
Public Class PGSQLParameters
    Inherits System.Collections.CollectionBase

    Public Enum SQLDecimalType
        SQLMoney = 1
        SQLDecimal = 2
    End Enum

#Region "COLLECTION ADD AND SUPPORT METHODS"
#Region "PUBLIC METHODS FOR ADDING ITEMS TO THE COLLECTION"
    '-- Input Parameter
    Public Overloads Sub Add(ByVal ParameterName As String,ByVal DataType As DbType,ByVal Size As Int32,ByVal Value As Object)
        If ParameterName.Length = 0 Then
            Return
        End If

        If TypeOf (Value) Is String AndAlso String.IsNullOrEmpty(Convert.ToString(Value)) Then
            Value = DBNull.Value
        End If

        If Not ParameterName.StartsWith(":") Then
            ParameterName = ParameterName.Insert(0,":")
        End If

        List.Add(BuildParameter(ParameterName,DataType,Size,ParameterDirection.Input,Value))
    End Sub

#Region "INPUT OVERLOADS"
    '-- String
    Public Overloads Sub Add(ByVal ParameterName As String,ByVal Value As String)
        Dim StringLength As Integer = 0

        If Not Value = Nothing AndAlso Not String.IsNullOrEmpty(Value) Then
            StringLength = Value.Length
        End If

        Add(ParameterName,DbType.String,StringLength,Value)
    End Sub
#End Region
#End Region

    Private Function BuildParameter(ByVal ParameterName As String,ByVal Direction As ParameterDirection,ByVal Value As Object) As NpgsqlParameter
        Dim NewParameter As NpgsqlParameter

        If Size > 0 Then
            NewParameter = New NpgsqlParameter(ParameterName,Size)
        Else
            NewParameter = New NpgsqlParameter(ParameterName,DataType)
        End If

        NewParameter.Direction = Direction

        If Not (Direction = ParameterDirection.Output AndAlso Value Is Nothing) Then
            NewParameter.Value = DBNull.Value

            If Not Value Is Nothing Then
                NewParameter.Value = Value
            ElseIf TypeOf (Value) Is Boolean Then
                NewParameter.Value = Value
            End If
        End If

        Return NewParameter
    End Function
#End Region

End Class
#End Region

我看不出有任何理由对 Parameters 集合进行这种自发的“清除”,特别是因为导致并包括“问题”的所有参数都是 String 值,因此它们'都使用完全相同的方法调用(我已经在我的演练中确认了这一点)。此外,根据正在执行的 SQL,它看起来实际上以某种方式保留集合对象中的前六个参数,只是不添加新参数,这完全没有意义.

此外,它看起来并没有完全重新实例化对象,因为如屏幕截图所示,Capacity 不会从第六个参数更改为第七个参数。如果我不得不说的话,它看起来像是在添加六个参数后克隆集合,然后丢弃该克隆和/或完全忽略它。再说一次,这对我来说毫无意义。

我不怀疑我只是忽略了某些东西,但我不知道那个“东西”是什么。有没有其他人遇到过这种行为?任何帮助或想法将不胜感激。如果我可以或需要提供任何其他详细信息,请告诉我。

解决方法

可能需要发布更多代码 - 发布的代码对我来说似乎没有任何问题:

enter image description here

将此图标拖到您的桌面上,将其重命名为 .zip 并打开它:

enter image description here

它有我用来检查您的问题的确切解决方案文件(它没有在我的计算机上显示问题)

,

我已经设法解决了这个问题,但原因是我没有预料到的,如果没有完整的更多代码列表,原因可能不会很明显。我很抱歉没有在原始问题中提供足够的细节,但我没有猜到我最终会在哪里找到问题的原因。

正如我上面指出的,问题总是出现在序列中的相同参数上。我试图分配给该特定参数的值是另一个类中 String 对象的公共属性 (Lazy(Of T))。

有问题的对象看起来像这样:

#Region "REAL ESTATE OBJECT"
''' <summary>
''' Standard object containing details about a specific piece of real estate
''' </summary>
Public Class RealEstate
#Region "PRIVATE FIELDS"
    <EditorBrowsable(EditorBrowsableState.Never)> <DebuggerBrowsable(DebuggerBrowsableState.Never)>
    Private _RealEstateTypeCode As String

    <EditorBrowsable(EditorBrowsableState.Never)> <DebuggerBrowsable(DebuggerBrowsableState.Never)>
    Private _PhysicalStreet1 As String

    <EditorBrowsable(EditorBrowsableState.Never)> <DebuggerBrowsable(DebuggerBrowsableState.Never)>
    Private _PhysicalStreet2 As String

    <EditorBrowsable(EditorBrowsableState.Never)> <DebuggerBrowsable(DebuggerBrowsableState.Never)>
    Private _PhysicalCity As String

    <EditorBrowsable(EditorBrowsableState.Never)> <DebuggerBrowsable(DebuggerBrowsableState.Never)>
    Private _PhysicalState As String

    <EditorBrowsable(EditorBrowsableState.Never)> <DebuggerBrowsable(DebuggerBrowsableState.Never)>
    Private _PhysicalZIPCode As String
#End Region

#Region "PRIVATE PROPERTIES"
    <EditorBrowsable(EditorBrowsableState.Never)> <DebuggerBrowsable(DebuggerBrowsableState.Never)>
    Private Property PGDB As PGSQLDB

#Region "LAZY PROPERTIES"
    ' >> THIS IS THE PROPERTY THAT APPEARS TO HAVE CAUSED THE ISSUE <<
    <EditorBrowsable(EditorBrowsableState.Never)> <DebuggerBrowsable(DebuggerBrowsableState.Never)>
    Private Property _RealEstateType As Lazy(Of PropertyType) =
    New Lazy(Of PropertyType)(Function()
                                    Return New PropertyType(_RealEstateTypeCode,Me.CIADB)
                                End Function)
#End Region
#End Region

#Region "PUBLIC PROPERTIES"
    Public Property RealEstateID As Integer

    Public Property PhysicalStreet1 As String
        Get
            Return _PhysicalStreet1
        End Get

        Set(value As String)
            If Not value Is Nothing Then
                If value.Trim.Length > 120 Then
                    _PhysicalStreet1 = value.Trim.Substring(0,120).Trim.ToUpper
                Else
                    _PhysicalStreet1 = value.Trim.ToUpper
                End If
            Else
                _PhysicalStreet1 = String.Empty
            End If
        End Set
    End Property

    Public Property PhysicalStreet2 As String
        Get
            Return _PhysicalStreet2
        End Get

        Set(value As String)
            If Not value Is Nothing Then
                If value.Trim.Length > 120 Then
                    _PhysicalStreet2 = value.Trim.Substring(0,120).Trim.ToUpper
                Else
                    _PhysicalStreet2 = value.Trim.ToUpper
                End If
            Else
                _PhysicalStreet2 = String.Empty
            End If
        End Set
    End Property

    Public Property PhysicalCity As String
        Get
            Return _PhysicalCity
        End Get

        Set(value As String)
            If Not value Is Nothing Then
                If value.Trim.Length > 60 Then
                    _PhysicalCity = value.Trim.Substring(0,60).Trim.ToUpper
                Else
                    _PhysicalCity = value.Trim.ToUpper
                End If
            Else
                _PhysicalCity = String.Empty
            End If
        End Set
    End Property

    Public Property PhysicalState As String
        Get
            If _PhysicalState Is Nothing OrElse String.IsNullOrEmpty(_PhysicalState) OrElse _PhysicalState = "XX" Then
                If Not _PhysicalZIPCode Is Nothing AndAlso Not String.IsNullOrEmpty(_PhysicalZIPCode) Then
                    _PhysicalState = Utility.GetStateCodeFromZIP(_PhysicalZIPCode)
                End If
            End If

            Return _PhysicalState
        End Get

        Set(value As String)
            If Not value Is Nothing Then
                If value.Trim.Length > 2 Then
                    _PhysicalState = Utility.GetStateCodeFromName(value.Trim)
                Else
                    If [Enum].IsDefined(GetType(USState),value.Trim.ToUpper) Then
                        Dim PState As USState

                        If [Enum].TryParse(value.Trim.ToUpper,PState) Then
                            _PhysicalState = Utility.GetStateCodeFromName(PState.GetEnumDescription)
                        End If
                    Else
                        _PhysicalState = value.Trim.ToUpper
                    End If
                End If
            Else
                _PhysicalState = "OK"
            End If
        End Set
    End Property

    Public Property PhysicalZIPCode As String
        Get
            Return _PhysicalZIPCode
        End Get

        Set(value As String)
            If Not value Is Nothing Then
                If value.Trim.Length > 10 Then
                    _PhysicalZIPCode = value.Trim.Substring(0,10).Trim.ToUpper
                Else
                    _PhysicalZIPCode = value.Trim.ToUpper
                End If
            Else
                _PhysicalZIPCode = String.Empty
            End If
        End Set
    End Property

    Public WriteOnly Property RealEstateTypeCode As String
        Set(value As String)
            _RealEstateTypeCode = value
        End Set
    End Property

    Public ReadOnly Property RealEstateType As PropertyType
        Get
            Return _RealEstateType.Value
        End Get
    End Property
#End Region

在我的原始混淆代码中,我只是注入了一个通用字符串作为占位符,但问题似乎与此特定分配有关。添加到参数列表的其他值是可立即访问的对象的“常规”属性。但是,在使用 Add() 参数的 Lazy(Of T) 对象调用 Value 方法时,某些东西似乎“短路”了。

为了“修复”这个问题,我声明了一个额外的本地 String 变量,用于从这个 Lazy(Of T) 对象中检索所需属性的值。然后我使用 局部变量 来分配给 Add() 方法的 Value 参数:

With REObject 'A RealEstate object
    ' > DECLARING THIS LOCAL VARIABLE TO RETRIEVE THE VALUE OF THE LAZY PROPERTY
    Dim TypeCode As String = .RealEstateType.TypeCode
...
    PGDB.Parameters.Add("street1",.PhysicalStreet1)
    PGDB.Parameters.Add("street2",.PhysicalStreet2)
    PGDB.Parameters.Add("city",.PhysicalCity)
    PGDB.Parameters.Add("state",.PhysicalState)
    PGDB.Parameters.Add("zip",.PhysicalZIPCode)
    ' > CHANGED THE FOLLOWING
    ' PGDB.Parameters.Add("type",.RealEstateType.TypeCode) 'String - THIS IS WHERE THE LIST CLEARS
    ' > TO USE THE LOCAL VARIABLE INSTEAD OF THE LAZY OBJECT'S PROPERTY VALUE
    PGDB.Parameters.Add("type",TypeCode)
    ' > THE VALUE IS NOW SUCCESSFULLY ADDED
...
End With

执行这段代码会导致所有参数正确填充正确的值,并且在数据库中执行的 SQL 语句没有错误。因此,似乎 Lazy(Of T) 对象尚未“填充”这一事实在进入 {{1} } 方法。老实说,我仍然不确定为什么它在尝试使用 Add() 对象的属性时“重置”了 .List 对象的 Collection 属性值,但至少这个分辨率达到了预期的目标。同样,我很抱歉最初没有提供足够的细节,但希望这会对其他人有所帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-