Reporting

Reporting

Old forum URL: forums.lhotka.net/forums/t/4680.aspx


dtabako posted on Saturday, April 12, 2008

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

RockfordLhotka replied on Saturday, April 12, 2008

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.

JonnyBee replied on Monday, April 14, 2008

Not knowing your requirements on database and reporting options my recommendations do follow Rockys advice, I would just like to add:

MS ReportViewer in "local mode" has no knowledge of the database and will work fine with CSLA objects, simple objects and datasets. However, if possible, I would choose to use ReportingServices for SQL Server and generate those reports on the Server. Ie, the report is created on the server but viewer is run locally or in a
web-browser - loaded from an  iis-server.

ReportingServices also supports parameters (and allows the user to set parameter values), however may not so flexible as your old app does out of the box.

You will find a lot more information on http://www.gotreportviewer.com 

/jonny

JoeFallon1 replied on Monday, April 14, 2008

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

 

dtabako replied on Monday, April 14, 2008

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

JoeFallon1 replied on Monday, April 14, 2008

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 ReportBaseFrame
 
Inherits DataDynamics.ActiveReports.ActiveReport3

There 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.ReportStart
 
mReadOnlyBO = GetReadOnlyBO()
 
mROC = GetROC()
End Sub

Protected 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

Protected Sub rpt_FetchData(ByVal sender As Object, ByVal eArgs As DataDynamics.ActiveReports.ActiveReport3.FetchEventArgs) Handles Me.FetchData

  '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 DollarReportBase
 
Inherits ReportBaseFrame

Public Overrides Function GetROC() As IReadOnlyList
 
Return DollarROC.GetDollarROC(GetSQLStatement)
End Function

Protected Overrides Function GetSQLStatement() As String
 
Return DollarDAO.GetSQLStatement(Me)
End Function

End Class

==================================================================

The code for the actual report looks like this: (because the Base class handles all the work)

Public Class ADollarReport
 
Inherits DollarDetailBase
End Class

There 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

dtabako replied on Monday, April 14, 2008

And thanks, Jonny, for your reply. I've looked through that site a bit and it seems helpful. Like I said in my other post, we're going to try to get this done with MySql but your link did give me some general help with MS Report Viewer as well. I will have to explore that site in more depth.

Copyright (c) Marimer LLC