MSDN Magazin > Home > Ausgaben > 2007 > January >  Datenpunkte: Spaltenausdrücke, Datenbezieh...
Datenpunkte
Spaltenausdrücke, Datenbeziehungen und Berechnungen
John Papa

Codedownload verfügbar unter: DataPoints2007_01.exe (191 KB)
Browse the Code Online

ADO.NET bietet weit mehr als nur die Möglichkeit, Daten in einer Datenbank zu speichern oder daraus abzurufen. Es stellt unzählige Features hinsichtlich Datenbearbeitung für Geschäftslogik und Anzeigezwecke in alltäglichen Anwendungen bereit. Wie in den Beispielen dieses Artikels zu sehen ist, eignet sich ADO.NET nicht nur für den Datenzugriff, sondern auch für die Datenbearbeitung.
Der Artikel dieses Monats befasst sich mit einigen der Fragen, die am häufigsten bezüglich der Datenbearbeitung mit ADO.NET gestellt werden. Es wird erläutert, wie Sie mithilfe ausdrucksbasierter Spalten und Datenbeziehungen (DataRelations) bestimmte Ziele erreichen können. Zudem wird erklärt, wie Sie mit einigen anderen Features, wie z. B. der Compute-Methode der Datentabelle (DataTable) und der SetOrdinal-Methode, häufig vorkommende Geschäftsanforderungen bewältigen können.

F: In einem Szenario sollen Auftragsdaten unter Verwendung von Datentabellen einzeln und in Gruppen (nach Tag, Monat und Jahr sortiert) angezeigt werden. Es muss möglich sein, die Auftragsdaten zu bearbeiten. Zudem müssen die Gesamtsummen in den übergeordneten Datentabellen die Änderungen sofort widerspiegeln. Jeder der Datensätze soll in getrennten Rastern auf dem Formular angezeigt werden. Wie können unter Verwendung von ADO.NET-Datenspaltenausdrücken nach dem Laden der Daten in eine Datentabelle die gruppierten Daten mit der Summe der Aufträge für jede Gruppe erstellt werden?
F: In einem Szenario sollen Auftragsdaten unter Verwendung von Datentabellen einzeln und in Gruppen (nach Tag, Monat und Jahr sortiert) angezeigt werden. Es muss möglich sein, die Auftragsdaten zu bearbeiten. Zudem müssen die Gesamtsummen in den übergeordneten Datentabellen die Änderungen sofort widerspiegeln. Jeder der Datensätze soll in getrennten Rastern auf dem Formular angezeigt werden. Wie können unter Verwendung von ADO.NET-Datenspaltenausdrücken nach dem Laden der Daten in eine Datentabelle die gruppierten Daten mit der Summe der Aufträge für jede Gruppe erstellt werden?

A: Berechnete Felder können problemlos entweder durch einen berechneten Ausdruck in einer SQL-Anweisung oder durch Erstellen einer ausdrucksgebundenen Datenspalte (DataColumn) erstellt werden. Es bestehen Unterschiede bei der Funktionsweise dieser beiden Methoden und bei den Features, die beide bereitstellen.
A: Berechnete Felder können problemlos entweder durch einen berechneten Ausdruck in einer SQL-Anweisung oder durch Erstellen einer ausdrucksgebundenen Datenspalte (DataColumn) erstellt werden. Es bestehen Unterschiede bei der Funktionsweise dieser beiden Methoden und bei den Features, die beide bereitstellen.
Für Ihr Szenario und Ihre Anforderungen sind berechnete Spalten in einer SQL-Anweisung nicht die optimale Lösung. Eine gute Lösung besteht darin, einer Reihe von Datentabellen ausdrucksbasierte Datenspalten hinzuzufügen.
Bevor auf dieses Problem näher eingegangen wird, sollten Sie einen Blick auf das angestrebte Endergebnis werfen (siehe Abbildung 1). Dieses Beispiel zeigt fünf Raster auf einem Formular. Das oberste Raster enthält die einzelnen Auftragspositionen. Preis, Menge und Preisnachlass jeder Auftragsposition können in diesem Raster bearbeitet werden. Nach Bearbeitung dieser Werte wird der erweiterte Preis für diese Zeile berechnet. Zudem werden die Werte der Gesamtsummen in den anderen vier Rastern automatisch neu berechnet. Die Änderungen schlagen sich in der aktualisierten Gesamtsumme nieder. Das zweite Raster enthält jeweils eine Zeile für jeden Auftrag, einschließlich einer berechneten Spalte, in der die Summe des erweiterten Preises für diesen Auftrag angezeigt wird. Das dritte, vierte und fünfte Raster enthält jeweils die Summe jedes Auftrags nach Tag, Monat bzw. Jahr sortiert.
Abbildung 1 Auftragsgesamtsumme sortiert nach Tag, Monat und Jahr (Klicken Sie zum Vergrößern auf das Bild)
Jedes Raster ist an eine andere Datentabelle gebunden. Die erste Datentabelle wird mit den Auftragspositionen aus der Datenbank geladen. Zudem ist an sie eine ausdrucksbasierte Spalte angehängt. Nachdem die Daten in die Datentabelle geladen wurden, wird mithilfe der Fill-Methode des Datenadapters (DataAdapter) eine Spalte mit der Bezeichnung „ExtendedPrice“ des Typs „Dezimal“ der Datentabelle hinzugefügt. Diese Spalte ist als Ausdrucksspalte definiert, deren Wert basierend auf den Werten von „UnitPrice“, „Quantity“ und „Discount“ für die jeweilige Datenzeile (DataRow) berechnet wird:
ds.Tables["OrderLines"].Columns.Add("ExtendedPrice", 
    typeof(decimal), "(UnitPrice * Quantity) * (1 - Discount)");
Die Datentabelle „OrderLines“ enthält die Kerndaten für dieses Formular. Sobald sie geladen und die Ausdrucksspalte erstellt wurde, kann die erste Datentabelle gefüllt und dem Datensatz (DataSet) hinzugefügt werden (siehe Abbildung 2). Die SQL-Anweisung ruft die Werte von „OrderID“ und „OrderDate“ für jeden Auftrag ab, und die Datentabelle wird mit den Ergebnissen gefüllt. Bevor dieser Datentabelle die Spalte „OrderTotal“ hinzugefügt wird, muss zunächst eine Datenbeziehung erstellt werden, damit der Ausdruck in dieser Datentabelle „Orders“ auf Spalten in der Datentabelle „OrderLines“ zugreifen kann.
using(SqlCommand cmd = new SqlCommand("SELECT o.OrderID, o.OrderDate " + 
    "FROM Orders o WHERE YEAR(o.OrderDate) = @year " +
    "ORDER BY o.OrderDate DESC", cn))
{
    cmd.CommandType = CommandType.Text;
    cmd.Parameters.AddWithValue("@year", year);
    SqlDataAdapter adpt = new SqlDataAdapter(cmd);
    DataTable orders = new DataTable("Orders");
    adpt.Fill(orders);
}
ds.Tables.Add(orders);
ds.Relations.Add("Orders2OrderLines", ds.Tables["Orders"].Columns["OrderID"], ds.Tables["OrderLines"].Columns["OrderID"]);
orders.Columns.Add("OrderTotal", typeof(decimal), 
    "Sum(Child.ExtendedPrice)");

Die Datenbeziehung wird zwischen den Spalten „OrderID“ der beiden Datentabellen eingerichtet. Dann kann die Ausdrucksspalte „OrderTotal“ erstellt und der Datentabelle „Orders“ hinzugefügt werden:
Sum(Child.ExtendedPrice) 
Der Child-Operator wird zunächst innerhalb und dann außerhalb der Klammer angewendet. Er teilt der Datenspalte „OrderTotal“ mit, zur untergeordneten Tabelle (Datentabelle „OrderLines“) zu navigieren und die Spalte „ExtendedPrice“ abzurufen. Unter erneuter Verwendung der Datenbeziehung addiert der Sum-Operator die Werte der Spalten „ExtendedPrice“ für die Zeilen in der Datentabelle „OrderLines“, deren „OrderID“-Werte mit den „OrderID“-Werten der übergeordneten Datentabelle übereinstimmen. Das Endergebnis ist, dass der Gesamtbetrag für jeden Auftrag in der Spalte „OrderTotal“ der Datentabelle „Orders“ angezeigt wird.
Bedenken Sie, dass bei mehreren Datenbeziehungen die Syntax verändert werden muss, um die jeweilige Datenbeziehung anzugeben. Das Beispiel aus Abbildung 2 würde nach entsprechender Änderung wie folgt aussehen:
Sum(Child(Orders2OrderLines).ExtendedPrice) 
Das gleiche Verfahren kann eingesetzt werden, um die Datentabelle „OrdersByDay“ zu füllen, die mit einer anderen Auftragsdatenliste aus der Datenbank geladen wird. Anschließend wird eine Datenbeziehung zwischen dieser Datentabelle und der zugehörigen Spalte „OrderDate“ und der Spalte „OrderDate“ der Datentabelle „Orders“ eingerichtet. Dadurch kann die Datentabelle „OrdersByDay“ die Auftragssummen in einer Spalte „OrderTotalByDay“ mithilfe von Ausdrücken zuordnen, wie hier zu sehen ist:
ds.Relations.Add("OrdersByDay2Orders", ds.Tables["OrdersByDay"].Columns["OrderDate"],
 ds.Tables["Orders"].Columns["OrderDate"]);

dayOrders.Columns.Add("OrderTotalByDay", typeof(decimal), 
    "Sum(Child.OrderTotal)");
Die letzten beiden Raster sind an Datentabellen gebunden, die auf die gleiche Art und Weise geladen werden. Dieses Verfahren könnte erweitert werden, um weitere Berechnungen zu zeigen. Zum Beispiel könnten Sie leicht ein Raster anzeigen, das die Auftragssummen für einen bestimmten Kunden enthält, solange die Kundeninformationen aus der Basistabelle abgerufen wurden. Mit einer Datenansicht (DataView) können Sie auch das Raster auf einer Ausdrucksspalte filtern.

F: Ein Szenario enthält eine übergeordnete Datentabelle („Orders“) und eine untergeordnete Datentabelle („OrderLines“). Die übergeordnete Datentabelle verfügt über eine Ausdrucksspalte für „OrderTotal“. Einige Spalten aus der übergeordneten Tabelle müssen in der untergeordneten Tabelle für jede Zeile angezeigt werden. Wie können Werte aus einer übergeordneten Tabelle abgerufen werden?
F: Ein Szenario enthält eine übergeordnete Datentabelle („Orders“) und eine untergeordnete Datentabelle („OrderLines“). Die übergeordnete Datentabelle verfügt über eine Ausdrucksspalte für „OrderTotal“. Einige Spalten aus der übergeordneten Tabelle müssen in der untergeordneten Tabelle für jede Zeile angezeigt werden. Wie können Werte aus einer übergeordneten Tabelle abgerufen werden?

A: Ausdrucksbasierte Spalten können mithilfe des Child-Operators auf Spalten in einer untergeordneten Datentabelle zugreifen. Sie können aber auch den Parent-Operator verwenden, um auf Spalten in einer übergeordneten Datentabelle zuzugreifen. Beispiel: Um auf den Wert einer Spalte in der übergeordneten Tabelle zuzugreifen, können Sie den Code aus dem vorherigen Beispiel ändern, um den folgenden Codeausschnitt hinzuzufügen:
ds.Tables["OrderLines"].Columns.Add("OrderTotalForOrderLinesTable", 
    typeof(decimal), "Parent.OrderTotal");
A: Ausdrucksbasierte Spalten können mithilfe des Child-Operators auf Spalten in einer untergeordneten Datentabelle zugreifen. Sie können aber auch den Parent-Operator verwenden, um auf Spalten in einer übergeordneten Datentabelle zuzugreifen. Beispiel: Um auf den Wert einer Spalte in der übergeordneten Tabelle zuzugreifen, können Sie den Code aus dem vorherigen Beispiel ändern, um den folgenden Codeausschnitt hinzuzufügen:
ds.Tables["OrderLines"].Columns.Add("OrderTotalForOrderLinesTable", 
    typeof(decimal), "Parent.OrderTotal");
Dieser Code fügt der untergeordneten Tabelle („OrderLines“) eine Ausdrucksspalte hinzu, die den Wert „OrderTotal“ aus der Datentabelle „Orders“ abruft. Diese neue Spalte muss nach dem Erstellen der unter- und übergeordneten Datentabellen, dem Einrichten der Datenbeziehung zwischen den beiden Tabellen und dem Erstellen der Spalte „OrderTotal“ erstellt werden. Diese Methode wird häufig verwendet, um eine Datenansicht einer untergeordneten Tabelle zu erstellen, die an ein Raster gebunden ist.
Wenn Sie den Parent-Operator mit Ausdrucksspalten verwenden, duplizieren Sie die übergeordneten Daten in die untergeordnete Datentabelle. Da die Tabellen synchronisiert sind, wird bei einer Änderung eines Werts in der übergeordneten Datentabelle dieser Wert auch in der untergeordneten Tabelle aktualisiert.

F: Ein Szenario enthält eine Datenrasteransicht (DataGridView), die an die Standardansicht (DefaultView) einer Datentabelle gebunden ist. Die Quelle der Datentabelle ist eine gespeicherte Prozedur, die Daten aus der Datenbank der Anwendung abruft. Alle Felder werden in einer bestimmten Reihenfolge zurückgegeben. Diese Felder müssen in der Datenrasteransicht jedoch in einer anderen Reihenfolge angezeigt werden. Wie können die Spalten in der Datenrasteransicht neu angeordnet werden?
F: Ein Szenario enthält eine Datenrasteransicht (DataGridView), die an die Standardansicht (DefaultView) einer Datentabelle gebunden ist. Die Quelle der Datentabelle ist eine gespeicherte Prozedur, die Daten aus der Datenbank der Anwendung abruft. Alle Felder werden in einer bestimmten Reihenfolge zurückgegeben. Diese Felder müssen in der Datenrasteransicht jedoch in einer anderen Reihenfolge angezeigt werden. Wie können die Spalten in der Datenrasteransicht neu angeordnet werden?

A: Manchmal ist es erforderlich, die Reihenfolge der Spalten in einer Datentabelle zu ändern, wenn die Reihenfolge der Felder in der SQL-Anweisung nicht einfach zu ändern ist. Die Datenspalte stellt eine SetOrdinal-Methode bereit, mit der Sie die Reihenfolge der Spalten in einer Datentabelle ändern können.
A: Manchmal ist es erforderlich, die Reihenfolge der Spalten in einer Datentabelle zu ändern, wenn die Reihenfolge der Felder in der SQL-Anweisung nicht einfach zu ändern ist. Die Datenspalte stellt eine SetOrdinal-Methode bereit, mit der Sie die Reihenfolge der Spalten in einer Datentabelle ändern können.
Die Ordinalpositionen sind 0-basiert. Um also die erste Spalte so zu verschieben, dass sie als vierte angezeigt wird, würden Sie den folgenden Code verwenden:
myDataTable.Columns[0].SetOrdinal(3);
Sie können auf die Spalte auch durch deren Namen statt durch deren Ordinalposition verweisen:
myDataTable.Columns["OrderID"].SetOrdinal(3);
Die Spalten vor der dritten Ordinalposition werden um eine Position verringert, um Platz für die Änderung der Positionierung zu schaffen.

F: Auf einem Bildschirm wird eine Liste mit Kunden anzeigt. Der Benutzer kann aus dieser Liste einen bestimmten Kunden auswählen und dessen vollständige Kundendaten angezeigen. Der Benutzer kann dann aus der Liste einen anderen Kunden auswählen und die Daten dieses Kunden einsehen. Es gibt zwei Möglichkeiten: Entweder werden sämtliche Kundendaten in eine Datentabelle geladen, und die Datenbank wird nur einmal abgefragt. Oder der Zugriff erfolgt lediglich auf die Liste der Kunden und deren IDs. Sobald der Benutzer dann einen Kunden auswählt, werden die Kundeninformationen aus der Datenbank abgerufen. Welche dieser Methoden ist besser?
F: Auf einem Bildschirm wird eine Liste mit Kunden anzeigt. Der Benutzer kann aus dieser Liste einen bestimmten Kunden auswählen und dessen vollständige Kundendaten angezeigen. Der Benutzer kann dann aus der Liste einen anderen Kunden auswählen und die Daten dieses Kunden einsehen. Es gibt zwei Möglichkeiten: Entweder werden sämtliche Kundendaten in eine Datentabelle geladen, und die Datenbank wird nur einmal abgefragt. Oder der Zugriff erfolgt lediglich auf die Liste der Kunden und deren IDs. Sobald der Benutzer dann einen Kunden auswählt, werden die Kundeninformationen aus der Datenbank abgerufen. Welche dieser Methoden ist besser?

A: Dies ist eine häufig gestellte Frage. Sollte die Datenbank einmal vollständig oder mehrere Male abgefragt werden? Wenn Sie eine Kundenliste und sämtliche darin enthaltenen Daten aus der Datenbank abrufen und die Ergebnisse in einem Datensatz speichern, rufen Sie viele Daten ab, die u. U. nie verwendet werden. Möglicherweise verhindern Sie dadurch aber wiederholte Abrufaktionen aus der Datenbank. Wenn z. B. 1.000 Kunden in der Kundentabelle vorhanden sind und Sie für jeden einzelnen Kunden auf 40 Spalten zugreifen, werden 40.000 Werte abgerufen und in der Datentabelle gespeichert. Die Liste der Kunden erfordert dagegen nur einen Anzeigewert (z. B. CompanyName) und eine ID (z. B. CustomerID). Die restlichen Spalten werden nur auf dem Bildschirm gezeigt, wenn der Benutzer einen bestimmten Kunden aus der Kundenliste auswählt.
A: Dies ist eine häufig gestellte Frage. Sollte die Datenbank einmal vollständig oder mehrere Male abgefragt werden? Wenn Sie eine Kundenliste und sämtliche darin enthaltenen Daten aus der Datenbank abrufen und die Ergebnisse in einem Datensatz speichern, rufen Sie viele Daten ab, die u. U. nie verwendet werden. Möglicherweise verhindern Sie dadurch aber wiederholte Abrufaktionen aus der Datenbank. Wenn z. B. 1.000 Kunden in der Kundentabelle vorhanden sind und Sie für jeden einzelnen Kunden auf 40 Spalten zugreifen, werden 40.000 Werte abgerufen und in der Datentabelle gespeichert. Die Liste der Kunden erfordert dagegen nur einen Anzeigewert (z. B. CompanyName) und eine ID (z. B. CustomerID). Die restlichen Spalten werden nur auf dem Bildschirm gezeigt, wenn der Benutzer einen bestimmten Kunden aus der Kundenliste auswählt.
Bei der anderen Option wird nur die Liste der Kunden mit dem Firmennamen (CompanyName) und der Kunden-ID (CustomerID) geladen. Sobald der Benutzer einen Kunden auswählt, ruft die Anwendung detaillierte Daten zu dem jeweiligen Kunden aus der Datenbank ab. Bei dieser Methode werden vorab wesentlich weniger Daten geladen, es werden aber häufiger Daten aus der Datenbank abgerufen.
Welche Lösung vorzuziehen ist, hängt von weiteren Faktoren ab. Wenn Sie z. B. so wenige Kundendaten haben, dass der Zugriff darauf sehr schnell ohne Leistungseinbußen unter Auslastungstests erfolgen kann, ist ein Abruf sämtlicher Daten vorab eine gute Wahl. Werden die Daten jedoch häufig geändert, hat diese Lösung einen großen Nachteil, da die geladenen Daten sehr schnell veralten. Bevor Sie entscheiden, alle Daten vorab in den Speicher zu laden, sollten Sie folgende Punkte berücksichtigen: die zum Laden der Daten erforderliche Zeit, den für die Daten erforderlichen Speicherbedarf, den Umfang der tatsächlich geladenen Daten und ob die Daten während des Ladevorgangs in der Datenbank verändert werden (wodurch die auf dem Bildschirm angezeigten Daten ungültig werden). Diese Methode eignet sich eher für kleinere Datensätze, die nicht im Hintergrund verändert werden.
Bei der zweiten Option werden die detaillierten Daten jedes Kunden nur abgerufen, wenn der Benutzer diese anfordert. Bei dieser Methode wird die Liste in der Regel schneller geladen, da weniger Daten geladen werden. Sie stellt auch aktuellere Daten bereit, da die einzigen sich nicht ändernden Daten in der Liste der Kunden enthalten sind. Der Nachteil dieser Methode besteht darin, dass die Anwendung immer dann auf die Datenbank zugreift, wenn der Benutzer einen Kunden auswählt. Folglich sollten die Aufrufe zum Abruf der Kundendaten optimiert werden, da Sie diese mit einem Schlüsselfeld (CustomerID) abrufen. Ziehen diese Aufrufe zum Abruf der Kundendaten eine merkliche Verzögerung nach sich, könnte dies an der Netzwerkbandbreite, der Abfrage selbst oder an Problemen mit der Datenübertragung durch die Architektur Ihrer Anwendung liegen. Wenn Sie sich für diese Methode entscheiden und dann eine Verlangsamung auftritt, müssen Sie deren Ursache ermitteln und herausfinden, ob dieses Problem gelöst werden kann.
Letztlich gibt es keine einfache Antwort für solche Entscheidungen. Die Antwort lautet fast immer, dass es von der jeweiligen Situation abhängt. Im Allgemeinen ist es aber besser, die Liste mit minimalen Daten zu laden und detaillierte Daten abzurufen, sobald der Benutzer einen bestimmten Eintrag auswählt. Bedenken Sie, dass die Leistung hier nicht das einzige Problem ist. Sie müssen auch bedenken, ob die Daten aktuell oder veraltet sind.

F: Eine Datenrasteransicht soll angezeigt werden, die mit Verkaufsdaten geladen wird, die an eine Datentabelle gebunden sind. Die Anwendung muss dem Benutzer ermöglichen, Berechnungen an den Verkaufsdaten im Raster durchzuführen und die Zeilen und Spalten auszuwählen, die in die Berechnung aufgenommen werden sollen. Wie können Berechnungen an der Datentabelle ermöglicht werden, ohne dass ein erneuter Zugriff auf die Datenbank erfolgt?
F: Eine Datenrasteransicht soll angezeigt werden, die mit Verkaufsdaten geladen wird, die an eine Datentabelle gebunden sind. Die Anwendung muss dem Benutzer ermöglichen, Berechnungen an den Verkaufsdaten im Raster durchzuführen und die Zeilen und Spalten auszuwählen, die in die Berechnung aufgenommen werden sollen. Wie können Berechnungen an der Datentabelle ermöglicht werden, ohne dass ein erneuter Zugriff auf die Datenbank erfolgt?

A: In diesem Fall ist die Compute-Methode die Lösung. Während ausdrucksbasierte Spalten jeweils auf eine einzelne Zeile angewendet werden, können Sie mit der Compute-Methode der Datentabelle Operationen an Zeilensätzen durchführen, sofern ein Filter und ein Ausdruck angegeben werden. Mit dem Filter können Sie festlegen, auf welche Zeilen die Compute-Methode angewendet werden soll, während der Ausdruck den auszuführenden Aggregatfunktionsausdruck angibt. Beispielsweise können Sie der Datentabelle eine Spalte hinzufügen, die die durchschnittliche Auftragssumme für Kunden in den Vereinigten Staaten berechnet. Dies ist ein großartiges Tool, um schnell Berechnungen an einem Zeilensatz durchzuführen, ohne dass ein erneuter Zugriff auf die Datenbank nötig ist.
A: In diesem Fall ist die Compute-Methode die Lösung. Während ausdrucksbasierte Spalten jeweils auf eine einzelne Zeile angewendet werden, können Sie mit der Compute-Methode der Datentabelle Operationen an Zeilensätzen durchführen, sofern ein Filter und ein Ausdruck angegeben werden. Mit dem Filter können Sie festlegen, auf welche Zeilen die Compute-Methode angewendet werden soll, während der Ausdruck den auszuführenden Aggregatfunktionsausdruck angibt. Beispielsweise können Sie der Datentabelle eine Spalte hinzufügen, die die durchschnittliche Auftragssumme für Kunden in den Vereinigten Staaten berechnet. Dies ist ein großartiges Tool, um schnell Berechnungen an einem Zeilensatz durchzuführen, ohne dass ein erneuter Zugriff auf die Datenbank nötig ist.
Abbildung 3 zeigt ein Beispielformular, das eine Liste mit Aufträgen zusammen mit der Gesamtsumme für jeden Auftrag enthält. Dieses Beispiel enthält alle grundlegenden Elemente, die der Ausdruck und der Filter erfordern. Auf der linken Seite des Gruppenfelds „Filter“ kann der Benutzer das zu filternde Feld, den auf das Feld anzuwendenden Operator und die Kriterien für den Filter auswählen. Die Liste der Felder wird gefüllt, indem sie an die Liste der Datenspalten gebunden wird:
DataColumn[] colList = new DataColumn[orders.Columns.Count];
orders.Columns.CopyTo(colList, 0);
ddlFilterColumn.DataSource = colList;
ddlFilterColumn.DisplayMember = "ColumnName";
Abbildung 3 Rechnen mit der Compute-Methode (Klicken Sie zum Vergrößern auf das Bild)
Dieser Code erstellt ein Datenspaltenarray, füllt dieses mit den Spalten aus der Datentabelle und bindet es an das Kombinationsfeld. Durch die Bindung des Datenspaltenarrays an das Kombinationsfeld ist ein Zugriff auf andere Eigenschaften der ausgewählten Datenspalte möglich, die verwendet werden können. Ist die ausgewählte Spalte z. B. eine Zeichenfolge, dann muss der Wert in Anführungszeichen gesetzt werden. Da die Datenspalte an das Kombinationsfeld gebunden ist, kann der Code ermitteln, ob der Wert in Anführungszeichen gesetzt werden muss.
Das Gruppenfeld „Calculation“ enthält sowohl eine Liste der Aggregatfunktionen als auch eine Liste der Spalten, für die die ausgewählte Aggregatfunktion verwendet werden soll. Die Liste der Spalten ist wie das ddlFilterColumn-Kombinationsfeld an das ddlCalculationColumn-Kombinationsfeld gebunden. Die Liste der Aggregatfunktionen wird mit den sieben in der Compute-Methode verfügbaren Funktionen geladen: Sum, Count, Avg, Min, Max, StDev und Var.
Durch Klicken auf die Schaltfläche wird der in Abbildung 4 dargestellte Code ausgeführt. Er bestimmt zunächst den Typ der ausgewählten Spalte für den Filter. Handelt es sich bei der Spalte um eine Zeichenfolge oder um ein Datum, wird der Kriterienwert in Anführungszeichen gesetzt. Sobald der Filter und der Ausdruck gebildet wurden, werden sie an die Compute-Methode weitergegeben, und das Ergebnis wird an das Textfeld übermittelt.
if (!ValidateControls()) return;

Type colType = ((DataColumn) (ddlFilterColumn.SelectedItem)).DataType;
string filterCriteria = string.Empty;
if (ddlFilterOperator.Text == "Like")
{
    filterCriteria = string.Format("'{0}%'", txtFilterCriteria.Text);
}
else 
{
    filterCriteria = (colType.Name == "String" || 
                      colType.Name == "DateTime") ? 
        string.Format("'{0}'", txtFilterCriteria.Text) : 
                               txtFilterCriteria.Text;
}
string filter = string.Format("{0} {1} {2}", ddlFilterColumn.Text, 
    ddlFilterOperator.Text, filterCriteria);
string expression = string.Format("{0}({1})", ddlAggregate.Text, 
    ddlCalculationColumn.Text);

object value = this.orders.Compute(expression, filter);
txtResult.Text = value.ToString();


Senden Sie Fragen und Kommentare für John in englischer Sprache an mmdata@microsoft.com.


John Papa ist leitender .NET-Berater bei ASPSOFT (aspsoft.com) und ein Baseballfan, der in den meisten Sommernächten mit seiner Familie und seinem treuen Hund Kadi die Yankees anfeuert. John Papa, ein C#-MVP, hat mehrere Bücher über ADO, XML und SQL Server verfasst. Er hält häufig Vorträge auf Branchenkonferenzen, wie z. B. VSLive, und führt einen Blog unter codebetter.com/blogs/john.papa.

Page view tracker