我在VS 2003中编写的VB .NET Web应用程序中,在框架1.1上收到以下错误。 Web应用程序在Windows Server 2000,IIS 5上运行,并且正在从在同一台计算机上运行的SQL Server 2000数据库中读取。
System.Data.ConstraintException: 无法启用约束。一个或 更多行包含违反的值 非null,唯一或外键 限制。在 System.Data.DataSet.FailedEnableConstraints() 在 System.Data.DataSet.EnableConstraints() 在 System.Data.DataSet.set_EnforceConstraints(布尔 价值) System.Data.DataTable.EndLoadData()
在 System.Data.Common.DbDataAdapter.FillFromReader(对象 data,String srcTable,IDataReader dataReader,Int32 startRecord,Int32 maxRecords,DataColumn parentChapterColumn,Object parentChapterValue)at System.Data.Common.DbDataAdapter.Fill(数据集 dataSet,String srcTable,IDataReader dataReader,Int32 startRecord,Int32 maxRecords)at System.Data.Common.DbDataAdapter.FillFromCommand(对象 data,Int32 startRecord,Int32 maxRecords,String srcTable, IDbCommand命令,CommandBehavior 行为) System.Data.Common.DbDataAdapter.Fill(数据集 dataSet,Int32 startRecord,Int32 maxRecords,String srcTable, IDbCommand命令,CommandBehavior 行为) System.Data.Common.DbDataAdapter.Fill(数据集 数据集)
当网络应用程序处于高负载时,会出现此问题。当卷不足时系统运行正常,但是当请求数变高时,系统开始使用上述异常消息拒绝传入的请求。一旦问题出现,很少有请求实际通过并正常处理,每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是否有可能以某种方式搞乱它应该传递给数据集的数据,从而导致由于数据类型/长度不匹配导致的约束违规?
我尝试访问检索到的数据集表中的数据行的RowError消息,但我一直得到空字符串。我知道有问题的数据表的HasErrors = true。我没有设置EnableConstraints = false,我不想这样做。
提前致谢。
雷
答案 0 :(得分:0)
问题是缺少有用的诊断错误消息。我编写了一个类,其中包含告诉您约束问题的方法,而不仅仅是给您一个无用的通用错误消息。您可以按以下方式使用这些方法。
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
现在您应该能够使用有用的信息进行故障排除。