ADO.NET limitation in validating XSD facets (811107)



The information in this article applies to:

  • Microsoft ADO.NET (included with the .NET Framework)
  • Microsoft ADO.Net 2.0

SYMPTOMS

ADO.NET does not throw any exceptions when it validates data that is newly inserted or modified in a DataRow. This is true if the DataRow violates XSD facets that are defined in an underlying XSD schema of the DataSet object.

CAUSE

ADO.NET currently validates only the length and maxLength facets for the XSD string primitive data type. All other XSD facets are ignored by ADO.NET when it validates data that is newly inserted or modified in a DataRow.

RESOLUTION

This is currently a known limitation in ADO.NET.

You can work around this problem by using a System.Xml.XmlValidatingReader object to validate the XML representation of the data in a DataSet against its underlying schema.

STATUS

This behavior is by design.

MORE INFORMATION

Steps to Reproduce the Behavior

  1. Use the following schema to create and save an XSD schema named Employee.xsd to the root folder of your hard disk:
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Employees" xmlns="urn:Employees">
    
      <xs:element name="Employee" type="EmployeeType"/>      
    
      <xs:simpleType name="InitialType">
      <xs:restriction base="xs:string">
        <xs:maxLength value="1"/>
      </xs:restriction>
      </xs:simpleType>
    
      <xs:simpleType name="AgeType">
      <xs:restriction base="xs:integer">
        <xs:minInclusive value="18"/>
        <xs:maxInclusive value="50"/>
      </xs:restriction>
      </xs:simpleType>
    
    
      <xs:complexType name="EmployeeType">
        <xs:sequence>  
          <xs:element name="EmployeeID" type="xs:string"/>
          <xs:element name="FirstName" type="xs:string"/>
          <xs:element name="MiddleInitial" type="InitialType"/>
          <xs:element name="LastName" type="xs:string"/>
          <xs:element name="age" type="AgeType"/>      
        </xs:sequence>    
      </xs:complexType>
    
    </xs:schema> 
    
  2. Using the Visual Studio .NET IDE, create a new Visual Basic .NET console application or use the Visual Studio 2005 IDE to create a new Visual Basic 2005 console application.
  3. In Module1.vb, paste the following code in Sub Main():
    Dim response As String
            Try
                Dim dsEmployees As System.Data.DataSet
                dsEmployees = New DataSet()
    
                Dim employeeTable As System.Data.DataTable
    
                dsEmployees.ReadXmlSchema("c:\Employee.xsd")
    
                employeeTable = dsEmployees.Tables("Employee")
    
                Dim employeeRow As System.Data.DataRow
                employeeRow = employeeTable.NewRow
    
                employeeRow("EmployeeID") = "E1"
                employeeRow("FirstName") = "Jim"
                employeeRow("MiddleInitial") = "AH"
                employeeRow("LastName") = "Stanton"
                employeeRow("age") = 60
    
                employeeTable.Rows.Add(employeeRow)
                Console.WriteLine("Row was added successfully")
            Catch ArgException As System.ArgumentException
                Console.WriteLine("Error occurred : " & ArgException.Message)
            Finally
                response = Console.ReadLine
            End Try
    
  4. Build and run the application.

    A System.ArgumentException is raised by the line of code that tries to add the invalid row to the Employee DataTable. The catch block displays the following error message that indicates that a value that is not valid was assigned to the MiddleInitial column:
    Error occurred : Cannot set column 'MiddleInitial' to 'AH'. The value violates the MaxLength limit of this column.
  5. Press any key to quit the program, and then change the value assigned to the MiddleInitial column to a single character "A", as shown in the following line of code:
    employeeRow("MiddleInitial") = "A" 
    
  6. Save, re-build, and then run the program. The Row was successfully added message appears in the Console window, indicating that the record was successfully added to the Employee DataTable without generating an exception to reflect that a value that is not valid is assigned to the Age column.

WORKAROUND

To work around this problem, use a System.Xml.XmlValidatingReader object to validate the XML representation of the data in a DataSet against its underlying schema.
  1. In Module1.vb, delete the existing code in Sub Main().
  2. In Module1.vb, paste the following code in Sub Main() . Study the in-line comments that explain the newly added code to validate the XML representation of the data in the DataSet by using a System.Xml.XmlValidatingReader object:
    Dim response As String
            Try
                Dim dsEmployees As System.Data.DataSet
                dsEmployees = New DataSet()
    
                Dim employeeTable As System.Data.DataTable
    
                dsEmployees.ReadXmlSchema("c:\employee.xsd")
    
                employeeTable = dsEmployees.Tables("Employee")
    
                Dim employeeRow As System.Data.DataRow
                employeeRow = employeeTable.NewRow
    
                employeeRow("EmployeeID") = "E1"
                employeeRow("FirstName") = "Jim"
                employeeRow("MiddleInitial") = "A"
                employeeRow("LastName") = "Stanton"
                employeeRow("age") = 60
    
                dsEmployees.Tables("Employee").Rows.Add(employeeRow)
    
                'Write out the Dataset's schema to disk.
                dsEmployees.WriteXmlSchema("c:\dsEmployeesSchema.xsd")
    
                'Create an instance of an XmlValidatingReader to parse the XML representation of the Dataset's data 
                '(obtained by calling the GetXml method of the Dataset.
                Dim rdr As New System.Xml.XmlValidatingReader(dsEmployees.GetXml, System.Xml.XmlNodeType.Element, Nothing)
    
                'Add an event handler to trap validation errors.
                AddHandler rdr.ValidationEventHandler, AddressOf ValidationEvent
    
                'Create an instance of an XmlSchemaCollection object to cache the dataset's schema.
                Dim sc As New System.Xml.Schema.XmlSchemaCollection()
                rdr.ValidationType = Xml.ValidationType.Schema
    
                'Add the XmlSchemaCollection to the XmlValidatingReaders schemas collection.
                rdr.Schemas.Add(Nothing, "c:\dsEmployeesSchema.xsd")
    
                'Parse the XML data.
                'Any validation errors experienced are trapped and reported by the 
                'ValidationEvent custom sub procedure that implements the System.Xml.Schema.ValidationEventHandler delegate.
                Do While rdr.Read
    
                Loop
    
            Catch exp As Exception
                Console.WriteLine("Error occurred : " & exp.Message)
            Finally
                response = Console.ReadLine
            End Try
    
  3. Add the following ValidationEvent custom Sub procedure to Module1.

    This procedure is an implementation of the System.Xml.Schema.ValidationEventHandler delegate. It is linked to the ValidationEventHandler event of the XmlValidatingReader object by the ADDHANDLER statement in Sub Main(). Any validation errors experienced by the XmlValidatingReader object as it parses the XML representation of the data in the DataSet appears in the Console window by the code in this procedure:
    Public Sub ValidationEvent(ByVal sender As Object, ByVal args As System.Xml.Schema.ValidationEventArgs)
            Console.WriteLine(args.Message)
    End Sub 
    
  4. Save, re-build, and then run the program. You receive the following validation error message in the Console window to report the invalid value assigned to the Age column. The error message displays the location of the error as present in the source XML representation of the data in the DataSet:

    The 'age' element has an invalid value according to its data type. An error occurred at (<line>,<col>).

The limitations of this workaround are that validation errors related to constraints defined as XSD facets can be identified only after the records are added to a DataTable; the error messages to report these errors are XML based as opposed to being DataSet oriented.

To locate the source line in the XML that generated the error, write out and examine the DataSet's XML (use the GetXml and WriteXml DataSet methods).You also have to useXmlValidatingReader to validate the data. This is the only known workaround to address this bug, and it can be used effectively to validate the data before updating a target data source with data that is not valid.

Modification Type:MinorLast Reviewed:3/9/2006
Keywords:kbbug KB811107 kbAudDeveloper