Exemplarische Vorgehensweise: Debuggen eines benutzerdefinierten SQL/CLR-Aggregats

Aktualisiert: November 2007

Dieses Thema gilt für folgende Anwendungsbereiche:

Edition

Visual Basic

C#

C++

Web Developer

Express

Standard

Pro und Team

Tabellenlegende:

Vorhanden

Nicht vorhanden

Befehl oder Befehle, die standardmäßig ausgeblendet sind.

In diesem Beispiel wird veranschaulicht, wie ein benutzerdefiniertes SQL/CLR-Aggregat gedebuggt wird. In der Beispieldatenbank AdventureWorks wird eine neue CLR/SQL-Aggregatfunktion mit dem Namen Concatenate erstellt. Wird diese Funktion in einer SQL-Anweisung aufgerufen, wird sie alle Werte einer angegebenen Spalte zu einem Eingabeparameter verketten.

Hinweis:

Je nach den aktiven Einstellungen oder der verwendeten Version können sich die angezeigten Dialogfelder und Menübefehle von den in der Hilfe beschriebenen unterscheiden. Klicken Sie im Menü Extras auf Einstellungen importieren und exportieren, um die Einstellungen zu ändern. Weitere Informationen finden Sie unter Visual Studio-Einstellungen.

So debuggen Sie eine CLR/SQL-Aggregatfunktion

  1. Stellen Sie in einem neuen SQL Server-Projekt eine Verbindung zur Beispieldatenbank AdventureWorks her. Weitere Informationen hierzu finden Sie unter Gewusst wie: Herstellen einer Verbindung zu einer Datenbank.

  2. Erstellen Sie mit dem Code aus dem Beispielabschnitt unten eine neue Funktion, und nennen Sie sie Concatenate.cs. Weitere Informationen finden Sie unter Gewusst wie: Entwickeln mit dem SQL Server-Projekttyp.

  3. Fügen Sie ein Skript hinzu, das die Funktion durch Einschließen in eine SELECT-Anweisung testet. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Verzeichnis TestScripts, wählen Sie Testskript hinzufügen aus, und fügen Sie den Code aus dem zweiten Beispielabschnitt dieser exemplarischen Vorgehensweise ein. Speichern Sie die Datei unter dem Namen Concatenate.sql. Klicken Sie mit der rechten Maustaste auf den Dateinamen, und klicken Sie anschließend auf Als Standardskript zum Debuggen festlegen.

  4. Fügen Sie in Concatenate.cs bei der if-Anweisung innerhalb der Accumulate-Methode einen Haltepunktein. Klicken Sie dazu auf den schattierten linken Rand des Text-Editor-Fensters, und klicken Sie im Menü Debuggen auf Start, um das Projekt zu kompilieren, bereitzustellen und einem Komponententest zu unterziehen. Wenn der durch einen gelben Pfeil gekennzeichnete Anweisungszeiger am Haltepunkt angezeigt wird, wird die Funktion gedebuggt.

  5. Testen Sie verschiedene Debugfeatures.

    1. Die Accumulate-Methode wird für jede Zeile der GROUP BY-Klausel des Skripts in Concatenate.sql einmal ausgeführt. Wenn Sie im Menü Debuggen wiederholt auf Einzelschritt klicken, können Sie verfolgen, wie das Ergebnis der Methode aufgebaut wird.

    2. Öffnen Sie im Fenster Lokal die Variable value, die den derzeit verarbeiteten Speichernamen enthält.

    3. Klicken Sie auf die Variable this. Der untergeordnete Knoten intermediateResult wird von dieser Funktion zurückgegeben und enthält sämtliche Speichernamen bis zu dem aktuellen miteinander verknüpft und durch Kommas getrennt.

    4. Doppelklicken Sie im Text-Editor auf die intermediateResult-Variable, um sie auszuwählen. Ziehen Sie intermediateResult in das Fenster Überwachen, und legen Sie die Variable an einer beliebigen Stelle im Fenster ab. Daraufhin wird die Variable der Liste der überwachten Variablen hinzugefügt.

    5. Führen Sie die Methode mehrmals aus. Der Wert von intermediateResult ändert sich bei jedem Methodendurchlauf, da ein zusätzlicher Speichername am Ende angehängt wird.

    6. Klicken Sie auf den Haltepunkt, um ihn zu entfernen, und fügen Sie bei der ersten Anweisung innerhalb der Terminate-Methode einen Haltepunkt ein. Diese Methode gibt dem Aufrufer das Ergebnis zurück. Klicken Sie im Menü Debuggen auf Start, um die Methode schrittweise auszuführen. Sie können sie jetzt schrittweise durchlaufen, indem Sie im Menü Debuggen auf Einzelschritt klicken. Halten Sie bei der return-Anweisung an.

    7. Klicken Sie nochmals auf Weiter, um das Debuggen der Funktion abzuschließen.

Beispiel

Dies ist der Code für die Aggregatfunktion, die in diesem Beispiel verwendet wird.

using System;
using System.Data.Sql;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.IO;
using System.Text;
[Serializable]
[SqlUserDefinedAggregate( 
    //use CLR serialization to serialize the intermediate result. 
    Format.UserDefined, 
    //Optimizer property: 
    IsInvariantToNulls=true,
    //Optimizer property: 
    IsInvariantToDuplicates=false,
    //Optimizer property: 
    IsInvariantToOrder=false,
    //Maximum size in bytes of persisted value: 
    MaxByteSize=8000)
] 
public class Concatenate: IBinarySerialize 
{ 
    /// <summary> 
    /// Variable holds intermediate result of the concatenation 
    /// </summary> 
    private StringBuilder intermediateResult; 
    /// <summary> 
    /// Initialize the internal data structures 
    /// </summary> 
    public void Init( ) 
    { 
        intermediateResult = new StringBuilder(); 
    } 
    /// <summary> 
    /// Accumulate the next value, nop if the value is null 
    /// </summary> 
    /// <param name="value"></param> 
    public void Accumulate(SqlString value) 
    { 
        if(value.IsNull) 
        { 
            return; 
        } 
        intermediateResult.Append(value.Value).Append(','); 
    } 
    /// <summary> 
    /// Merge the partially computed aggregate with this aggregate. 
    /// </summary> 
    /// <param name="other"></param> 
    public void Merge( Concatenate other) 
    { 
        intermediateResult.Append(other.intermediateResult); 
    } 
    /// <summary> 
    /// Called at end of aggregation, to return results. 
    /// </summary> 
    /// <returns></returns> 
    public SqlString Terminate() 
    { 
        string output = string.Empty; 
        //Delete the trailing comma, if any .
        if (intermediateResult != null && intermediateResult.Length > 0) 
            output = intermediateResult.ToString(0, intermediateResult.Length-1); 
        return new SqlString(output); 
    } 
    public void Read(BinaryReader r) 
    { 
        intermediateResult = new StringBuilder(r.ReadString()); 
    } 
    public void Write(BinaryWriter w) 
    { 
        w.Write(intermediateResult.ToString()); 
    } 
}

Dies ist das Testskript, das die Funktion aufruft.

SELECT scu.SalesPersonID, dbo.Concatenate(sst.Name)
FROM Sales.Customer as scu 
INNER JOIN Sales.Store as sst
    ON scu.CustomerID    = sst.CustomerID
INNER JOIN Sales.SalesPerson as spr
    ON scu.SalesPersonID = spr.SalesPersonID
WHERE    scu.SalesPersonID = 283
GROUP BY scu.SalesPersonID

Siehe auch

Aufgaben

Gewusst wie: Erstellen und Ausführen eines CLR SQL Server-Aggregats

Weitere Ressourcen

Debuggen von SQL CLR-Datenbanken