Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

Crystal Reports mit DataSets befüllen - Teil 1

Geschrieben von: Rudolf Ball
Kategorie: ADO.NET

This printed page brought to you by AlphaSierraPapa

Nicht immer ist es optimal, einen Report direkt aus einer Datenbank zu befüllen. Man wünscht sich, Daten kurz vor dem Anzeigen noch zu manipulieren. Ob es sich nun um das Hinzufügen von Werten oder korrektes Runden handelt, in jedem Fall ist das Unterlegen eines DataSets hinter Crystal Reports eine gelungene Alternative. Anhand eines durchgängigen Beispiels werden die Vorteile von DataSets und XML Schemas aufgezeigt.

DataSets bieten sich als Quelle für den Inhalt eines Reports an, da sie von der Datenbank disconnected sind. Doch es ist ein wenig knifflig, dieses DataSet hinter den Report zu schieben. Dies wird Ihnen anhand dieses Beispiels nähergebracht: Es wird eine Kochrezeptdatenbank angelegt, und auf einer Website können Sie das zu kochende Gericht wählen, welches Ihnen als Report angezeigt wird.

Systemüberblick

Auf der Seite Default.aspx haben wir die Möglichkeit, ein Rezept unserer Wahl auszuwählen. Es wird die Seite Report.aspx aufgerufen, welche einen CrystalReportViewer enthält - dieser referenziert auf einen Report. Es wird eine Verbindung zu einem SQL Server erzeugt, welcher ein DataSet zurückliefert. Bevor wir dieses DataSet hinter den Crystal Report legen, manipulieren wir den Inhalt noch ein wenig.

Ein Ziel des Beispiels war es, eine Master-Detail Beziehung im Report korrekt darzustellen. In unserem Fall handelt es sich um die Beziehung "Rezept hat Zutaten". Das Datenbankdiagramm sieht wie folgt aus:

Default.aspx

Die Seite Default.aspx enthält eine Dropdownliste, welche die Rezepte anzeigt:

Als DataText Eigenschaft setzen wir den Wert "Rezeptname", als DataValue Eigenschaft jedoch die RezeptID, welche bei Klick des "Anzeigen" Buttons als Parameter im Querystring mitübergeben wird. Das PageLoad Event der Default.aspx Seite sieht wie folgt aus:

if (!Page.IsPostBack)
{
   DataSet4Report myDS4R = new DataSet4Report();
   ddRezepte.DataSource = myDS4R.Rezepte();
   ddRezepte.DataTextField = "Rezeptname";
   ddRezepte.DataValueField = "RezeptID";
   ddRezepte.DataBind();
}

Als erstes fangen wir das PostBack Event ab. Nach Erzeugung eines neuen DataSet4Report Objekts (siehe nächste Sektion) weisen wir den Rückgabewert der Methode Rezepte(), ein DataReader, der Dropdownliste zu.

Die DataSet4Report Klasse

Um die Daten aus der Datenbank zu bekommen benötigen wir eine Datenklasse (DataSet4Report.cs). Wir werden exemplarisch die Methode Kochrezept beschreiben, welche ein DataSet mit zwei Tabellen, Rezept und Zutaten, zurückliefert.

public DataSet Kochrezept(int RezeptID)
{
   DataSet dsKochrezept = null;
   SqlConnection mySqlConnection = null;
   SqlCommand myCommand = null;		
   SqlDataAdapter myDA = null;
   DataRelation myDR = null;
   DataColumn columnMaster = null;
   DataColumn columnDetail = null;

Gleich am Anfang dieser Methode definieren wir alle Variablen, die wir später noch benötigen. Die zwei DataColumns columnMaster und columnDetail werden uns in der Relation myDR die Verbindung zwischen den zwei Tabellen (1:n) definieren.

try
{
   dsKochrezept = new DataSet("Kochrezept");
   mySqlConnection = new SqlConnection(connectionString);
   string query = "SELECT * FROM Rezept WHERE RezeptID='" + RezeptID.ToString() + "';";
   mySqlConnection.Open();
   myCommand = new SqlCommand(query, mySqlConnection);
   myDA = new SqlDataAdapter (myCommand);
   myDA.Fill(dsKochrezept, "Rezept");
   query = "SELECT * FROM Zutaten WHERE RezeptID='" + RezeptID.ToString() + "';";
   myCommand = new SqlCommand(query, mySqlConnection);
   myDA.SelectCommand = myCommand;
   myDA.Fill(dsKochrezept, "Zutaten");
   mySqlConnection.Close();

Nachdem wir das DataSet "Kochrezept" initialisiert haben, erzeugen wir eine SqlConnection zur Datenbank. Das dynamisch erzeugte Command wird gegen die Datenbank abgesetzt. Ein DataAdapter erzeugt und füllt die Tabelle "Rezept" in das DataSet. Dieser Vorgang wird für die Tabelle "Zutaten" wiederholt. Da wir die Datenbankverbindung nun nicht mehr benötigen, schließen wie sie.

   columnMaster = dsKochrezept.Tables["Rezept"].Columns["RezeptID"];
   columnDetail = dsKochrezept.Tables["Zutaten"].Columns["RezeptID"];
   myDR = new DataRelation("RezeptZutaten", columnMaster, columnDetail);
   dsKochrezept.Relations.Add(myDR);
   return dsKochrezept;
}
catch (Exception ex)
{
   throw ex;
}

Nun möchten wir die Relation zwischen den Tabellen darstellen. Aus diesem Grund müssen wir die Schlüsselspalten (RezeptID) definieren. Diese werden columnMaster und columnDetail bezeichnet. Auch die Relation wird dem DataSet "Kochrezept" hinzugefügt, welches wir retournieren. Die zweite Methode der Klasse DataSet4Report.cs namens "Rezepte" liefert als Rückgabewert einen DataReader mit der gesamten Tabelle "Rezept".

Report.aspx

Nachdem wir auf der Seite Default.aspx den Button "anzeigen" geklickt haben, werden wir auf die Seite Report.aspx gelinkt. Diese Seite beinhaltet einen CrystalReportViewer, welcher per "Drag and Drop" von der Toolbox auf die Designansicht der Seite gezogen werden kann.

Das PageLoad Event von Report.aspx sieht wie folgt aus:

private void Page_Load(object sender, System.EventArgs e)
{
   try
   {
      this.RezeptID = Int32.Parse(Request.Params["RezeptID"]);
   }
   catch
   {
      Response.Redirect("default.aspx");
   }
}

Hier wird nur der Parameter RezeptID aus der URL ausgelesen und der privaten Eigenschaft RezeptID zugewiesen. Sollte jedoch keine Zahl übergeben werden wird eine Exception ausgelöst, der "catch" Abschnitt des "try" Blocks aufgerufen und auf die Startseite default.aspx redirected. Als nächstes müssen wir den Load-Event des Reports implementieren. Diesen erzeugen wir am einfachsten über die Eigenschaften des ReportViewers, wie folgendes Bild zeigt:

private void OnViewerLoad(object sender, System.EventArgs e)
{
   RezeptReport myReport = new RezeptReport();
   DataSet4Report myDS4R = new DataSet4Report();
   DataSet ReportSet = myDS4R.Kochrezept(this.RezeptID);

Hier wird eine neue Instanz unseres Reports "RezeptReport" sowie eine neue Instanz unserer Datenklasse erstellt. Ein DataSet namens ReportSet wird mit Hilfe der Methode Kochrezept gefüllt. Da wir aber nicht das DataSet pur übernehmen wollen, sondern eine Manipulation vornehmen werden, fügen wir im folgenden Code dafür hinzu.

   DataRow myNewRow = ReportSet.Tables["Zutaten"].NewRow();
   myNewRow["RezeptID"] = this.RezeptID.ToString();
   myNewRow["Zutat"] = "Gesamtkosten";
   double kosten = 0;
   foreach (DataRow x in ReportSet.Tables["Zutaten"].Rows)
   {
      kosten = kosten + double.Parse(x["Kosten"].ToString());
   }
   myNewRow["Kosten"] = kosten.ToString();
   ReportSet.Tables["Zutaten"].Rows.Add(myNewRow);

Wir füllen die Spalte "RezeptID", "Zutat" und "Kosten". Um die Gesamtkosten zu errechnen, durchlaufen wir das DataSet mit einer foreach-Schleife und addieren die Einzelkosten der Zutaten. Am Schluß fügen wir die neue Reihe der DataSet Tabelle "Zutaten" hinzu. Jetzt müssen wir nur noch das DataSet hinter den Report klemmen.

   myReport.SetDataSource(ReportSet);
   this.CrystalReportViewer1.ReportSource = myReport;
}

Dem Report myReport wird als Datenquelle das DataSet zugewiesen, dem ReportViewer der Report.

Schlußbemerkung

Wie dieser Report erstellt wurde, sehen Sie in Teil 2 dieser Artikelserie. Bis dahin viel Spaß beim "Nachkochen" der heute vorgestellten Rezepte!

This printed page brought to you by AlphaSierraPapa

Verwandte Artikel

Crystal Reports mit DataSets befüllen - Teil 2
http:/www.aspheute.com/artikel/20030403.htm
Datenbankzugriff mittels ADO.NET
http:/www.aspheute.com/artikel/20001102.htm

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.