Introduction
I couldn't find a proper description of how to use CrystalReports push model in VS2005 or anywhere else, so everything that was found during three weeks of struggle is in this article.
Background
CrystalReports supports two data models: push and pull. The second one is quite simple: you define a connection string during design time and CRE (CrystalReports Engine) uses it to generate a report based on your template.
One can also provide custom connection string before running the report, but anyway CRE works with tables directly.
But what if there is a requirement to utilize stored procedures instead of tables and to cache some data beforehand or to use a datasource unknown to CRE? Then push model should go.
Unfortunately, there is (or was) very little information on how to actually implement these push mechanisms especially for CRE for .NET apart from a good and simple example of what to do in VS2005 of how to create a report with push model, but without any custom data adapters: "Creating Crystal Reports using C# with Datasets". However in my case, the report was quite complex and should have remained intact and the solution proposed in the article just didn't fit: too much code to write all by myself, whereas Visual Studio Wizards cover almost (almost) everything.
Using the Code
There is very little code itself, because VS generates almost everything automatically.
First of all, a report template is required (prepare/acquire one yourself).
I. Generate a Data Source using Visual Studio Interface, Which Includes:
- Data → Add New Data Source
- Database
- New Connection
- etc.
II. Take Whatever Wizards Created and Make a Custom Data Source Based on the Standard Code
Note: Changes affect automatically generated adapters classes (one for each table in my case).
I just copy-pasted the generated code removing hard coded values like connection string extraction from the application configuration file and replacing it with my custom method of obtaining database connections (variable is called _connection
and I set it in InitConnection()
to null
).
You can also update SqlCommand
s objects in InitCommandCollection
that are used to extract data from the database.
Note: Each adapter class for each table has its own connection and collection of commands.
Change Fill
method to work with your custom connection and any parameters you wish to provide (stored procedure parameters in my case).
Note: At the end of Fill
method there is an actual call, which is this.Adapter.Fill(dataTable)
. The thing is that InitCommandCollection
is called internally and if you provide some, say, stored procedure parameters via Fill
then store them in internal variables and supply during the initialization.
III. Usage
- Create your custom dataset like
CustomDataSet ds = new CustomDataSet()
- Create as many adapters as required
- Call
Fill
method for each of the adapters with any parameters you want (provided method's interface has been amended) - As the first parameter of the
Fill
method is a dataset object (or collection of objects), after all Fill
methods complete, you will get a dataset filled with all requested data - Supply your report object with the dataset generated
Points of Interest
It was quite amazing to spend so much time resolving such a relatively minor problem, because there is no explanation of what to do.
History