Has anyone used MS Reporting (i.e. ReportViewer) or Crystal Reports in conjunction with CSLA? I am rewriting an application that was originally written in a proprietary unix-based, non-GUI environment. Most of the functionality provided through .NET and CSLA is improving the app 1000-fold. However, one of the old app's strong points was a very flexible reporting system. There was a standard reporting interface from which users could choose from dozens of fields to set up filtering and sorting options. Filtering could be done on any of those fields through either a range or a list (or, of course, no filter). The sorting options included the ability to set up grouping with group-break headers and page-breaks on groups. Users could also save named reports and load those reports later to avoid having to re-enter a lot of options.
I'm looking to recreate this reporting functionality as closely as possible. If anyone has any ideas or could help point me in the right direction it would be greatly appreciated. The reporting piece is a huge piece of my app and it would be a huge advance if I could develop a good standard interface from which I could easily derive all my reports.
Thanks,
Dennis
I divide "reporting" into two concepts: lists and reports.
Lists are a type of "report" that requires relatively little data (even if the output is lengthy, the data required is relatively small). Lists can often be created based on existing objects in your object model, and so are quite approachable from a CSLA perspective - just bind your reporting tool to your objects (on the client) and away you go.
Reports are a type of "report" that requires more than a little data (even if the output is very short!). Reports should be created directly from the database. Trying to load objects (or datasets or anything) and then create a report is inherently inefficient and should be avoided. You are far better off using a reporting tool that can efficiently get the data directly from the database. Ideally reports are created on an app server (or maybe even the database server), even though they are viewed on the client.
FWIW
We tried hard to get Reporting Services to work inside our Web app and found far too many issues with it.
We have been using Data Dynamics Active Reports for a couple of years now and they are great to work with. I set up a framework where a ReadOnly BO contains the header data and a ROC contains the details and we have been able to produce every report from our old system. We allow users to enter complex sets of criteria and save those sets with names for later re-use.
We wanted to go down the road of having users "design" reports by selecting fields, etc but we never had the time or expertise to get that done.
Joe
Thanks for all the replies. Rocky, I assume what you're suggesting is some sort of reporting service correct? That's not the kind of thing I've really ever worked with but, like most things with this project, I guess I can get myself into it hip-deep soon enough ;^) Any specifics that could help dumb it down for me? BTW at this point, we're using MySql rather than SQL Server. I doubt that will change unless we find compelling reason to do so.
Joe, your solution sounds interesting. Like you, my original hope was to allow users to "design" their reports but I also don't have the experience or time to go down that road. I think if I could get the app out there with the type of reporting features you describe I could focus on upgrading the reporting capabilities for version 2. I'd be interested to hear any implementation details you could share.
Thanks everyone, Dennis
One of the really nice things about Active Reports is that the reports are nothing more than normal .Net classes. So everything you have learned can be re-used in normal class style code.
At a high level we have a Base class:
Public
Class ReportBaseFrameThere are many Properties and methods - some key ones include:
Public Overridable Function GetReadOnlyBO() As IMyReadOnlyObject
Public Overridable Function GetROC() As IReadOnlyList
Protected Overridable Function GetSQLStatement() As String
By using interfaces I can cast various BOs and ROCs to the Interface and utilize their common properties. I had to add a few to the standard CSLA interfaces.
Here is where we handle the main Active Reports events:
Protected
Sub rpt_ReportStart(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ReportStartProtected
Sub rpt_DataInitialize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.DataInitialize 'this uses reflection to set all properties of the report outside the Detail section.
End Sub
'this uses reflection to set all properties of the report in the Detail section and is called once per row of data in the ROC.
End Sub
==================================================================
Then for a specific family of reports we use inheritance like this: (there might be 10 similar reports for Dollars - by supplier, by buyer, by requisitioner, etc.)
Public
Class DollarReportBaseEnd Class
==================================================================
The code for the actual report looks like this: (because the Base class handles all the work)
Public
Class ADollarReportThere is obvioulsy a lot of code omitted but the idea is pretty straightforward. Once you have the framework written, building new reports is pretty simple.
I omitted the whole UI side of things where complex criteria are saved to the DB and passed to these reports. There is a lot of interaction goigng on. But the key is Active Reports is just a set of classes.
The only issue I had with them is that the report engine will not do a sort for you. You have to feed it pre-sorted data. But once you get past that it is not a major adjustment.
Joe
Copyright (c) Marimer LLC