Nested Objects in Local Mode
As I have mentioned before, the Reporting Services team regularly reviews the bug reports and feature requests that come in via Connect. Shortly after the release of Visual Studio 2010, we started to receive a few requests and questions through Connect. One of them, however, stood out from all the others in terms of volume – nested objects in local mode were failing with #Error. It wasn’t long before calls started to come in through customer support as well.
As we started to investigate the problem, it became clear that this wasn’t a simple issue. The further we dug into the code, the more we realized that this wasn’t going to be easy to fix. There was a lot of pressure to publish a hotfix to immediately fix the problem. However the architecture change needed was of sufficiently high risk that we didn’t want to rush this out and break something else. Since this has been such a high volume problem, I want to dedicate an article to not only explaining the fix, but also some history into the problem.
Report Processing in VS 2005 and VS 2008
The processing engine used by the VS 2005/2008 ReportViewer in local mode is based on the SQL Server 2005 report processing engine. That engine reads the entire data set and processes the entire report before rendering the first page. That means that any data needed to evaluate expressions on any of the pages is calculated up front. When you are using an object data source, the object sits in memory from the time you hand it to the Report Viewer up until it is used to evaluate expressions. The pre-calculated expressions are stored in a report snapshot along with a serialized version original object data.
During most interactivity with the report, such as navigating pages or expanding drilldowns, only the calculated expression values are referenced. The original data isn’t touched. This works just fine for the vast majority of cases. If the original data isn’t touched, then why do we store it? There is one case in VS 2005/2008 where we do need to recalculate some of the expression values – during an end user sort. Resorting the data has the potential to change the report in far more significant ways than any other interactivity. The original data is needed to recalculate the expression values in this case.
During our investigation into the nested objects problem, we learned that there is one case that doesn’t work in VS 2005/2008 – nested objects in local mode after a user sort. The processing engine in those releases was correctly serializing all of the top level properties into the report snapshot. But it failed to do this correctly for nested objects. Enabling user sort is not the most frequently used feature in RDL, but it seems that in all of the years local mode was available, no one, including us, used it local mode with an object data source that uses nested objects. In VS 2005/2008, this scenario produces the same #Error that has become such a hot topic in VS 2010.
Report Processing in VS 2010
Something obviously changed in VS 2010 to make this problem much more apparent. The change is rooted in the fact that the VS 2010 local mode is based on a newer version of the report processing engine - the SQL Server 2008 version. One of the major updates in that processing engine is that it is an on-demand processing engine. Unlike previous versions where all report expressions were calculated up front, this engine only calculates the expressions that are needed at the moment. This tends to improve performance since we never spend time calculating values that you don’t ask to see.
One of the consequences to this workflow change is that the snapshot is created first, with processing and rendering always executing off of that snapshot. The in-memory objects from the object data source are never directly used by the renderer as was the case before. The same serialization problem we had in earlier versions was unknowingly carried forward into VS 2010. But now it happens with any rendering of the report, not just after a user sort.
We spent a great deal of time evaluating this problem and quickly realized that it wasn’t going to be an easy fix. It was certainly too big to address in a hotfix. But we have fixed this in Visual Studio 2010 SP1, with one caveat. In order to make nested objects available to the processing engine, they must be placed in the report snapshot. Therefore, in order to get nested objects working again, we are adding the requirement that the objects in your data hierarchy be serializable. This allows us to place them in the snapshot and make them available to the processing engine for expression evaluation. This has the added benefit of not only bringing us to parity with VS 2005/2008, but also fixing the long broken user sort scenario.
Thank you for your patience with this issue and thanks to all of you who have worked with us directly in analyzing this problem. I certainly apologize for the delay in getting this fix out to you, but I hope that this delay has allowed us to deliver the cleanest and least impactful fix.