Web applications SQL Server 2000的神秘约束问题

Web applications SQL Server 2000的神秘约束问题,web-applications,sql-server-2000,constraints,strongly-typed-dataset,Web Applications,Sql Server 2000,Constraints,Strongly Typed Dataset,我在Framework1.1上从VS2003中编写的一个VB NET web应用程序中得到以下错误。该web应用程序正在Windows Server 2000 IIS 5上运行,并正在从同一台计算机上运行的SQL Server 2000数据库中读取数据 System.Data.ConstraintException: 未能启用约束。一个或多个 更多行包含违反规则的值 非空、唯一或外键 限制。在 System.Data.DataSet.FailedEnableConstraints 在 Syste

我在Framework1.1上从VS2003中编写的一个VB NET web应用程序中得到以下错误。该web应用程序正在Windows Server 2000 IIS 5上运行,并正在从同一台计算机上运行的SQL Server 2000数据库中读取数据

System.Data.ConstraintException: 未能启用约束。一个或多个 更多行包含违反规则的值 非空、唯一或外键 限制。在 System.Data.DataSet.FailedEnableConstraints 在 System.Data.DataSet.EnableConstraints 在 System.Data.DataSet.set_EnforceConstraintsBoolean 价值 System.Data.DataTable.EndLoadData 在 System.Data.Common.DbDataAdapter.FillFromReaderObject 数据,字符串,表格,IDataReader 数据读取器,Int32 startRecord,Int32 maxRecords,数据列 parentChapterColumn,对象 parentChapterValue位于 System.Data.Common.DbDataAdapter.FillDataSet 数据集,字符串srcTable,IDataReader 数据读取器,Int32 startRecord,Int32 maxRecords在 System.Data.Common.DbDataAdapter.FillFromCommandObject 数据,Int32 startRecord,Int32 maxRecords,字符串srcTable, IDbCommand命令,CommandBehavior 行为 System.Data.Common.DbDataAdapter.FillDataSet 数据集,Int32 startRecord,Int32 maxRecords,字符串srcTable, IDbCommand命令,CommandBehavior 行为 System.Data.Common.DbDataAdapter.FillDataSet 数据集

当web应用程序处于高负载状态时,会出现此问题。当容量较低时,系统运行正常,但当请求数较高时,系统开始拒绝传入的请求,并显示上述异常消息。一旦问题出现,很少有请求真正通过并得到正常处理,大约每30个请求中就有2个请求。在执行SQL Server重新启动或IIS重置之前,绝大多数请求都会失败。然后,系统开始正常处理请求,一段时间后,它开始抛出相同的错误

当数据适配器对SELECT语句运行Fill方法以填充强类型数据集时,会发生此错误。数据集似乎不喜欢给定的数据,并引发此异常。此错误发生在作用于不同表的各种SELECT语句上

我已经重新生成了数据集并检查了相关的约束,以及从中读取数据的表。数据集定义和表中的数据都很好

诚然,考虑到当前接收到的传入请求数量,运行web应用程序和SQL Server 2000的硬件已经严重过时。SQL Server消耗的RAM量是动态分配的,在峰值时间,SQL Server最多可以消耗服务器上3.5 GB内存中的2.8 GB

起初我怀疑某种索引或数据库损坏,但在运行DBCC CHECKDB之后,在数据库中没有发现任何错误。所以现在我想知道这个错误是否是系统硬件限制的结果。SQL Server是否可能以某种方式弄乱它应该传递给数据集的数据,从而导致由于(例如)数据类型/长度不匹配而违反约束

我尝试访问检索到的dataset表中数据行的RowError消息,但始终得到空字符串。我知道hasrerrors=true用于讨论中的数据表。我没有设置EnableConstraints=false,我不想这样做

提前谢谢


Ray

问题在于缺少有用的诊断错误信息。我已经编写了一个类,其中包含一些方法来告诉您约束的问题,而不仅仅是给您一条无用的通用错误消息。您可以按以下方式使用这些方法

Dim ds As New dsMyDataset

'Turn off constraints during the data load'
DatasetAnalyzer.DatasetAnalyzer_Init(ds)

'Ready to fill one or more tables'
Dim da1 As New dsMyDatasetTableAdapters.Table1TableAdapter
da1.Fill(ds.Table1)

'Checks relationships and constraints before turning them back on.'
DatasetAnalyzer.DatasetAnalyzer_AnalyzeAndConfirm(ds)

'Ready to use your dataset now'
Return ds
这是完整的课程

Public Class DatasetAnalyzer

#Region " DatasetAnalyzer "

    'Run this before loading tables in your dataset, if you plan to call DatasetAnalyzer_GetMissingParentRows.
    'Must call DatasetAnalyzer_AnalyzeAndConfirm when done creating dataset to re-enable relations.
#Region " DatasetAnalyzer_Init "
    Public Shared Sub DatasetAnalyzer_Init(ByVal ds As Data.DataSet)
        ds.EnforceConstraints = False

        ds.BeginInit()
        For Each dt As Data.DataTable In ds.Tables
            dt.BeginInit()
            dt.BeginLoadData()

        Next

    End Sub
#End Region

    'Checks for dataset constraint errors and gives detailed error messages if any are found.
    'Assumes DatasetAnalyzer_Init is called on that dataset
#Region " DatasetAnalyzer_AnalyzeAndConfirm "
    Public Shared Sub DatasetAnalyzer_AnalyzeAndConfirm(ByVal ds As Data.DataSet)
        DatasetAnalyzer_EnsureInitialization(ds)

        Try
            For Each dt As Data.DataTable In ds.Tables
                dt.EndLoadData()
                dt.EndInit()
            Next
            ds.EndInit()

            ds.EnforceConstraints = True

        Catch ex As Data.ConstraintException
            'We've found a constraint exception...figure out what it is

            Dim sErrorMessage As String = "DatasetAnalyzer_AnalyzeAndConfirm : "

            For Each oTbl As Data.DataTable In ds.Tables
                If oTbl.HasErrors Then

                    'Report the first error only
                    Dim oRow As Data.DataRow = oTbl.GetErrors(0)
                    sErrorMessage &= oTbl.TableName & " : " & oRow.RowError & " : "

                    'Detail for Foreign Key Violations
                    If oTbl.ParentRelations IsNot Nothing Then
                        For Each oRel As Data.DataRelation In oTbl.ParentRelations
                            If oRel.ChildKeyConstraint IsNot Nothing AndAlso oRow.GetParentRow(oRel) Is Nothing Then
                                'a parent constraint for this relation exists and the data that is constrained is non-existant.  If this isn't a null value then we found a problem
                                For Each o As Data.DataColumn In oRel.ChildColumns
                                    If Not oRow.IsNull(o) Then
                                        'We have a confirmed foreign key violation...generate a pretty message

                                        Dim ParentColumnNames(oRel.ParentColumns.Length - 1) As String
                                        Dim ChildColumnNames(oRel.ChildColumns.Length - 1) As String


                                        For i As Int32 = 0 To ParentColumnNames.Length - 1
                                            ParentColumnNames(i) = oRel.ParentColumns(i).ColumnName
                                        Next

                                        For i As Int32 = 0 To ChildColumnNames.Length - 1
                                            ChildColumnNames(i) = oRel.ChildColumns(i).ColumnName
                                        Next

                                        sErrorMessage &= "ParentTable = " & oRel.ParentTable.TableName & " (" & String.Join(", ", ParentColumnNames) & "), "
                                        sErrorMessage &= "ChildTable = " & oRel.ChildTable.TableName & " (" & String.Join(", ", ChildColumnNames) & "), "

                                    End If
                                Next
                            End If
                        Next
                    End If


                    'Additional Column info that might be usefull
                    If oRow.RowError.Contains("MaxLength") Then
                        For Each oCol As Data.DataColumn In oRow.GetColumnsInError
                            sErrorMessage &= oCol.ColumnName & ".MaxLength = " & oCol.MaxLength
                        Next
                    End If


                    'Report the error with details about the row that errored
                    sErrorMessage &= Environment.NewLine & Environment.NewLine & "Debug Data = " & DatasetAnalyzer_GetRowDebugData(oRow)
                    Throw New Exception(sErrorMessage)

                End If
            Next


            Throw New Exception("Dear Developer, Unknown Constraint Exeption", ex)
        End Try

    End Sub
#End Region

    'Returns an array of detached rows that are "missing" in the ParentTable.
    'Returns an empty array if no values exist
#Region " DatasetAnalyzer_GetMissingParentRows "
    Public Shared Function DatasetAnalyzer_GetMissingParentRows(ByVal ParentTable As Data.DataTable) As Data.DataRow()
        If ParentTable.DataSet Is Nothing Then
            Throw New Exception("Dear Developer, DatasetAnalyzer_GetMissingParentRows : ParentTable must belong to a dataset.  Table = " & ParentTable.TableName)
        End If

        DatasetAnalyzer_EnsureInitialization(ParentTable.DataSet)

        Dim drMissingParents As New Collections.Generic.List(Of Data.DataRow)

        Try
            'Turn on the constraints to see if anything breaks
            ParentTable.DataSet.EnforceConstraints = True

        Catch ex As Data.ConstraintException

            For Each oRel As Data.DataRelation In ParentTable.ChildRelations
                If oRel.ChildKeyConstraint IsNot Nothing AndAlso oRel.ChildTable.HasErrors Then
                    'This relationship has a child key constraint...this child table has errors

                    For Each oRow As Data.DataRow In oRel.ChildTable.GetErrors
                        If oRow.GetParentRow(oRel) Is Nothing Then
                            ' This foreign key that is constrained is non-existant.  If this isn't a null value then we found a problem
                            For Each o As Data.DataColumn In oRel.ChildColumns
                                If Not oRow.IsNull(o) Then
                                    ' non-null missing foreign key constraint
                                    Dim drMissingParent As Data.DataRow = ParentTable.NewRow

                                    ' Create the proposed parent record by matching the child record
                                    For i As Int32 = 0 To oRel.ParentColumns.Length - 1
                                        drMissingParent(oRel.ParentColumns(i)) = oRow(oRel.ChildColumns(i))
                                    Next

                                    'Search for a duplicate Missing Parent...only need to report each one once
                                    Dim bFoundDupe As Boolean = False
                                    For Each dr As Data.DataRow In drMissingParents
                                        bFoundDupe = True

                                        For i As Int32 = 0 To ParentTable.Columns.Count - 1
                                            If Not dr(i).Equals(drMissingParent(i)) Then
                                                bFoundDupe = False
                                                Exit For
                                            End If
                                        Next

                                        If bFoundDupe Then Exit For
                                    Next

                                    If Not bFoundDupe Then
                                        drMissingParents.Add(drMissingParent)
                                    End If

                                    Exit For 'Checking for non-nulls Columns
                                End If
                            Next
                        End If
                    Next
                End If
            Next
        End Try

        ParentTable.DataSet.EnforceConstraints = False

        Return drMissingParents.ToArray
    End Function
#End Region

    'Returns the string representation of row data
#Region " DatasetAnalyzer Private Support Methods "

    Private Shared Function DatasetAnalyzer_GetRowDebugData(ByVal oRow As Data.DataRow) As String
        Dim Values(oRow.Table.Columns.Count - 1) As String


        For Each oCol As Data.DataColumn In oRow.Table.Columns
            Dim Value As String
            If oRow.IsNull(oCol) Then
                Value = "<NULL>"
            Else
                Value = oRow(oCol).ToString
            End If

            Values(oCol.Ordinal) = oCol.ColumnName & ":" & Value
        Next


        Return String.Join(", ", Values)
    End Function

    Private Shared Sub DatasetAnalyzer_EnsureInitialization(ByVal ds As Data.DataSet)
        If ds Is Nothing Then
            Throw New Exception("Dear Developer, Must construct the ds object before calling InDatasetAnalyzer_Init (ds = New ...)")
        End If

        If ds.EnforceConstraints Then
            Throw New Exception("Dear Developer, call DatasetAnalyzer_Init before calling DatasetAnalyzer_AnalyzeAndConfirm")
        End If
    End Sub
#End Region
#End Region

End Class
现在,您应该能够使用有用的信息进行故障排除