In my previous post I stated that I had succeeded in converting a Reporting Services Data Processing Extension for reporting on ad-hoc data from a serialized ADO.Net DataSet into VB.Net. I have since extended this with an extra parameter (IDataParameterCollection) to allow the report designer to define at design-time (or indeed at run-time) which DataTable within the DataSet should be used as the source table. The implementation of DataProcessing.IDataReader also now iterates over a DataView of the table rather than the DataTable itself thus allowing me to pass a third parameter (actually passed via the Generic Query Designer as the command text (IDbCommand.CommandText)) which I then use as the RowFilter for the DataView.
This all works great. I can supply the parameters which I have told the extension to request from the designer (via the implementation of IDbCommandAnalysis.GetParameters method), and the query designer screen returns the data into the results screen, but if I attempt to navigate to the report layout tab, or I click on the 'Refresh Fields' button within the Generic Query Designer, I get an exception.
I deliberately decided to Debug.Assert that the @DataSource parameter should not be empty, but it should not be empty anyway as I have already supplied it via the designer. Following my debug trace information I can see that ExecuteReader in being called, but that the parameters are being passed as empty strings. If I elect to ignore the error then I can see via the trace that ExecuteReader gets called a second time, this time passing the parameters as I have entered them, and all is well.
The solution of course is not to require there to be non-empty parameters, but surely this is a bug?
UPDATE: after lots more detective work I have discovered that presumably the Report Designer graciously handles any ArgumentExceptions, and just carries on and attempts the ExecuteReader a second time.
How did I discover this? I turned off my assertions and just let the code proceed, the code gets as far as trying to load the DataSet:
Try
dataset.ReadXml(dataSource)
Catch ex As System.Exception
Trace.WriteLine(String.Format("Error Reading XML into dataset: {0}:{1}", ex.Message, ex.GetType))
Throw ex
End Try
but inevitably it fails because the dataSource parameter is a blank string, so I catch an ArgumentException and write a message to the trace as follows:
Error Reading XML into dataset: The path is not of a legal form.:System.ArgumentException
The Report Designer then carries on and repeats the call to ExecuteReader, this time passing the correct parameters and everything goes smoothly.
So, still a bug in my opinion (unless anyone can enlighten me otherwise) - but it works!
UPDATE 2:
Robert Bruckner has now kindly enlightened me as follows (see also this thread):
If you actually execute the query when ExecuteReader(SchemaOnly) is called
then the implementation is incorrect. For SchemaOnly execution, no parameter
values are passed in because no query should be executed – just the columns
should be returned.When Refreshing Fields, the report designer first tries to determine the
fields based on ExecuteReader(SchemaOnly) because this should not affect any
database state (and it is cheaper). If SchemaOnly fails, then report
designer tries to actually execute the query and determine the fields based
on the returned dataset. In order to execute the query it has to pass in
parameter values.