1

Je reçois l'erreur suivante d'une application Web VB NET écrite dans VS 2003, sur le framework 1.1. L'application Web s'exécute sur Windows Server 2000, IIS 5 et lit à partir d'une base de données SQL Server 2000 exécutée sur la même machine.Problème de contraintes mystérieuses avec SQL Server 2000

System.Data.ConstraintException: Echec de l'activation des contraintes. Un ou plusieurs lignes contiennent des valeurs non conformes aux contraintes non nulles, uniques ou à clé étrangère . à System.Data.DataSet.FailedEnableConstraints() à System.Data.DataSet.EnableConstraints() à System.Data.DataSet.set_EnforceConstraints (valeur booléenne ) à System.Data.DataTable.EndLoadData()
à System.Data.Common.DbDataAdapter.FillFromReader (Object données, String srcTable, IDataReader datareader, Int32 startRecord, Int32 maxRecords, DataColumn parentChapterColumn, objet parentChapterValue) à System.Data.Common.DbDataAdapter.Fill (DataSet dataSet, String s rcTable, IDataReader datareader, Int32 startRecord, Int32 maxRecords) à System.Data.Common.DbDataAdapter.FillFromCommand (Object données, Int32 startRecord, Int32 maxRecords, String srcTable, commande IDbCommand, le comportement CommandBehavior ) au système .Data.Common.DbDataAdapter.Fill (DataSet dataSet, Int32 startRecord, Int32 maxRecords, String srcTable, commande IDbCommand, le comportement CommandBehavior System.Data.Common.DbDataAdapter.Fill) à (jeu de données)

dataSet

Le problème apparaît lorsque l'application Web est soumise à une charge élevée. Le système fonctionne correctement lorsque le volume est faible, mais lorsque le nombre de demandes devient élevé, le système commence à rejeter les demandes entrantes avec le message d'exception ci-dessus. Une fois que le problème apparaît, très peu de demandes parviennent à le faire et sont traitées normalement, environ 2 fois sur 30. La grande majorité des demandes échouent, jusqu'à ce qu'un redémarrage de SQL Server ou qu'une réinitialisation IIS soit effectuée. Le système commence alors à traiter les demandes normalement et, après un certain temps, il commence à émettre la même erreur.

L'erreur se produit lorsqu'un adaptateur de données exécute la méthode Fill() par rapport à une instruction SELECT pour remplir un ensemble de données fortement typé. Il semble que l'ensemble de données n'aime pas les données qui lui sont données et rejette cette exception. Cette erreur se produit sur diverses instructions SELECT, agissant sur des tables différentes.

J'ai régénéré l'ensemble de données et vérifié les contraintes pertinentes, ainsi que la table à partir de laquelle les données sont lues. La définition de l'ensemble de données et les données du tableau sont correctes.

Il est vrai que le matériel en cours d'exécution à la fois l'application Web et SQL Server 2000 est sérieusement dépassée, compte tenu du nombre de demandes entrantes qu'il reçoit actuellement. La quantité de RAM consommée par SQL Server est allouée dynamiquement et, aux heures de pointe, SQL Server peut consommer jusqu'à 2,8 Go sur un total de 3,5 Go sur le serveur. Au début, je soupçonnais une sorte de corruption d'index ou de base de données, mais après l'exécution de DBCC CHECKDB, aucune erreur n'a été détectée dans la base de données. Retour au début |Alors maintenant, je me demande si cette erreur est le résultat des limitations matérielles du système. Est-il possible que SQL Server gâche d'une manière ou d'une autre les données qu'il est censé transmettre à l'ensemble de données, entraînant une violation de contrainte due, disons, à une différence de type/longueur de données?

J'ai essayé d'accéder aux messages RowError des lignes de données dans les tables de jeux de données récupérées mais j'ai continué à obtenir des chaînes vides. Je sais que HasErrors = true pour les datatables en question. Je n'ai pas défini EnableConstraints = false et je ne veux pas le faire.

Merci d'avance.

Ray

Répondre

0

Le problème est l'absence d'un message d'erreur de diagnostic utile. J'ai écrit une classe qui contient des méthodes pour vous dire le problème avec vos contraintes au lieu de simplement vous donner un message d'erreur générique inutile. Vous utilisez les méthodes de la façon suivante.

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 

Voici la classe complète.

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 

Maintenant, vous devriez être en mesure de résoudre les problèmes avec des informations utiles.