Neo and Crystal Reports

Using Crystal Reports with Neo, as with any other ORM framework, can be tricky, since CR are oriented primarily for fetching data from databases (or "in-memory databases", datasets). However, with some effort this can be done. Actually, I know two ways of doing that.

1st way. We can use the Context's DataSet object as the datasource. As it is not a typed DataSet, we might have some trouble at the design stage, so we should make some preparation.

Preparation

  1. First we have to obtain the dataset schema. The easiest way is to load all tables using Neo, and then use Context.DataSet.WriteXmlSchema.
  2. Now, create a new dataset and paste the schema into the xsd editor. We have a typed DataSet with the same schema as Neo's.

Design time
Design your report using the new strongly typed DataSet.

Run time
Use the ReportDocument's SetDataSource method to show your data.

2nd way. In many cases showing your database data is not enough, because you have many custom properties that don't exist in the dataset. The new 2005 version of Crystal Reports can use IEnumerable as data source. However, it still thinks of it as some sort of a database copy.

Design time

  1. Create your report in the same project as your entities.
  2. When prompted for a data source, choose Project Data, .NET Objects, and select all entity classes (not collections) for your report. For example, if you want to list your movies with corresponding categories, select bot Movie and Category objects
  3. CR ignored object relationships. It thinks that objects are related through some sort of foreign keys. So, we should have included the ID column for Category and the CategoryID column for Movie. Now we have to manually link these properties.
  4. The rest is the same as with datasets. If you change your entity classes at some point, click "Verify Database", and it'll reload the class structure. You can use all value type properties as data fields.

Run time

  1. Create your enumerables. Say, you have MyMovies of type MovieList and MyCategories of type CategoryList.
  2. Now we don't have a single datasource, so we can't use SetDataSource. Instead, we use something like this:
    reportDocument1.Database.Tables("Support_Category").SetDataSource(MyCategories);

There is one big problem with this approach: performance. When CR load your enumerable, they check all public properties (not just value types), even if they are not used in the report. So, for every movie, they'll compute the Category property, meaning that they make a db query (unless it's already cached by Neo). So, you either preload all objects using FindAllObjects (could work for categories, but not for large tables), or you preload all that you need using spans and then switch db off by setting IgnoresDataStore to true.

Still, I'd go for the second way, since adding custom properties to Crystal Reports is a very painful procedure.

ulu

Labels

 
(None)