views:

210

answers:

2

Good afternoon,

An XML schema validation snippet is working fine on development/q&a environments, but is yielding some odd validation results in Production. The usual suspect would be that the code is unsafe for threading, and that the additional load of the Production scenario is flushing out the error.

The exact scenario is as follows. Consider that the XML being validated is:

<mssql:spExecute type="ResultSet" xmlns:mssql="urn:namespace">
    <mssql:actor>IPASS</mssql:actor>
    <mssql:connection>ConnectionString</mssql:connection>
    <mssql:storedProcedure>dbo.RedFox</mssql:storedProcedure>
</mssql:spExecute>

In the course of a full day, around 300 executions (of >2M) will yield the following exception:

System.Xml.Schema.XmlSchemaValidationException
The 'http://www.w3.org/2000/xmlns/:mssql' attribute is not declared.

The schema validator seems to complain about the namespace declaration.

The code structure is as follows:

  • There is a static instance of XmlSchemaSet;
  • Initialization of the XmlSchemaSet instance is being done in a thread-safe manner;
  • Each worker thread makes use of the same XmlSchemaSet;
  • The validation occurs during an XmlSerializer.Deserialize() call, using an XmlReader with XmlReaderSettings initialized with ValidationType.Schema.

Any thoughts on what might be causing the validation to choke with the namespace declaration?

+1  A: 

I had the same problem. It seems that XML validation is not a read-only operation, which this article indicates:

http://blogs.msdn.com/xmlteam/archive/2009/04/27/xmlschemaset-thread-safety.aspx

Sticking a lock around it solved the problem for me.

marijne
No. It's not. Read again. The article says that validation uses only read-only operations on `XmlSchemaSet` so multiple threads can share single `XmlSchemaSet` instance without explicit locks.It points out that a) `XmlSchemaSet` construction is not thread safe and b) you need to make sure the `ValidationEventHandler` callback you provide is thread-safe.Both are pretty obvious.What it does not say is _why it assumes read-only operations on `XmlSchemaSet` are indeed thread-safe_. Documentation says "any instance members [including property reads --ts] are not guaranteed to be thread safe."
Tomek Szpakowicz
er, it's not read-only if it's not thread safe...
marijne
@marijne Could you elaborate? By what definition of read-only? Is there any official definition what "read-only operation" means in .NET Framework? __And how to say---looking at a class from outside---if an operation is read-only?__ Remember, any kind of lazy evaluation results in an operation that---while externally read-only---changes internal state of an object.For `XmlSchemaSet`, which is compiled before use, it makes sense to expect that all reads are truly read-only. The problem is, documentation doesn't say so openly and I'm not sure if I can safely cache compiled schema.
Tomek Szpakowicz
A: 
  1. Is what you describe a result of a controlled experiment or an observation from production environment? If the latter, try reproducing it in a controlled setup to make sure some other bug is not a real cause.

  2. The documentation for XmlSchemaSet says:

    "Any instance members are not guaranteed to be thread safe."

    This includes property reads and "read-only" methods. So we cannot assume that read-only use of XmlSchemaSet would be thread safe. Until Microsoft provides implementation that explicitly allows sharing of some compiled schema representation between threads, the only safe thing to do is not share.

  3. OTOH it seems logical to share single compiled immutable XmlSchemaSet to validate multiple XmlDocument (or XmlReader) instances. It is a very sensible scenario, so I don't understand why it is not explicitly permitted and documented.

    (Update: Apparently this is explicitly guaranteed in Java's standard XML library. Why isn't it so in .NET?)

Tomek Szpakowicz