Anforderungen für den benutzerdefinierten Typ

Sie müssen mehrere wichtige Entwurfsentscheidungen treffen, wenn Sie einen benutzerdefinierten Typ (UDT, user-defined type) für die Installation in Microsoft SQL Server erstellen. Für die meisten UDTs wird das Erstellen als Struktur empfohlen, obwohl auch das Erstellen als Klasse möglich ist. Die UDT-Definition muss den Spezifikationen für das Erstellen von UDTs entsprechen, um mit SQL Server registriert werden zu können.

Anforderungen für das Implementieren von UDTs

Um in SQL Server ausgeführt zu werden, muss der UDT die folgenden Anforderungen in der UDT-Definition implementieren:

Der UDT muss das Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute angeben. Die Verwendung des System.SerializableAttribute-Schlüsselworts ist optional, wird aber empfohlen.

  • Der UDT muss die System.Data.SqlTypes.INullable-Schnittstelle in der Klasse oder Struktur durch Erstellen einer öffentlichen static (Shared in Microsoft Visual Basic) Null-Methode implementieren. SQL Server erkennt standardmäßig NULL-Werte. Dies ist notwendig für Code, der im UDT ausgeführt wird, um in der Lage zu sein, einen NULL-Wert zu erkennen.

  • Der UDT muss eine öffentliche static (oder Shared) Parse-Methode enthalten, die die Analyse unterstützt, sowie eine öffentliche ToString-Methode für das Konvertieren in eine Zeichenfolgendarstellung des Objekts.

  • Ein UDT mit benutzerdefiniertem Serialisierungsformat muss die System.Data.IBinarySerialize-Schnittstelle implementieren und eine Read- sowie eine Write-Methode bereitstellen.

  • Der UDT muss System.Xml.Serialization.IXmlSerializable implementieren. Andernfalls müssen alle öffentlichen Felder und Eigenschaften Typen entsprechen, die durch XML serialisierbar sind oder das XmlIgnore-Attribut erhalten, wenn das Außerkraftsetzen einer Standardserialisierung erforderlich ist.

  • Es darf nur eine Serialisierung eines UDT-Objekts geben. Die Überprüfung schlägt fehl, wenn die Serialisierungs- oder Deserialisierungsroutinen mehr als eine Darstellung eines bestimmten Objekts erkennen.

  • SqlUserDefinedTypeAttribute.IsByteOrdered muss true sein, damit Daten in Bytereihenfolge verglichen werden können. Wenn die IComparable-Schnittstelle nicht implementiert wird und SqlUserDefinedTypeAttribute.IsByteOrderedfalse ist, treten bei Vergleichen der Bytereihenfolge Fehler auf.

  • Ein in einer Klasse definierter UDT muss über einen öffentlichen Konstruktor verfügen, der keine Argumente verwendet. Sie können optional zusätzliche überladene Klassenkonstruktoren erstellen.

  • Der UDT muss Datenelemente als öffentliche Felder oder Eigenschaftenprozeduren verfügbar machen.

  • Öffentliche Namen dürfen nicht länger als 128 Zeichen sein und müssen den SQL Server-Benennungsregeln für Bezeichner entsprechen, die in Bezeichner definiert sind.

  • sql_variant-Spalten können keine Instanzen eines UDTs enthalten.

  • Auf vererbte Member kann nicht von Transact-SQL aus zugegriffen werden, da das SQL Server-Typsystem die Vererbungshierarchie zwischen UDTs nicht kennt. Sie können Vererbung allerdings verwenden, wenn Sie Klassen strukturieren, und Sie können diese Methoden in der verwalteten Codeimplementierung des Typs aufrufen.

  • Mit Ausnahme des Klassenkonstruktors können Member nicht überladen werden. Wenn Sie eine überladene Methode erstellen, wird kein Fehler ausgelöst, wenn Sie die Assembly registrieren oder den Typ in SQL Server erstellen Erkennung der überladenen Methode tritt zur Laufzeit auf, nicht beim Erstellen des Typs. Überladene Methoden können in der Klasse vorhanden sein, solange sie nie aufgerufen werden. Sobald Sie eine überladene Methode aufrufen, wird ein Fehler ausgelöst.

  • Alle static- oder Shared-Member müssen als Konstanten oder als schreibgeschützt deklariert werden. Statische Member können nicht änderbar sein.

  • Wenn das SqlUserDefinedTypeAttribute.MaxByteSize-Feld auf -1 festgelegt wurde, kann die serialisierte UDT so groß wir die Größenbeschränkung für große Objekte (LOB, Large Object) sein (zurzeit 2 GB). Die Größe des UDTs kann den im MaxByteSized-Feld angegebenen Wert nicht überschreiten.

HinweisHinweis

Obwohl sie vom Server zum Durchführen von Vergleichen nicht verwendet wird, können Sie optional die System.IComparable-Schnittstelle implementieren, die eine einzelne Methode, nämlich CompareTo, bereitstellt Diese Methode wird auf Clientseite in Situationen verwendet, in denen UDT-Werte präzise verglichen oder geordnet werden sollen.

Systemeigene Serialisierung

Die Auswahl der richtigen Serialisierungsattribute für den UDT hängt vom Typ des UDTs ab, den Sie erstellen möchten. Das Native-Serialisierungsformat nutzt eine sehr einfache Struktur, die SQL Server ermöglicht, eine effiziente systemeigene Darstellung des UDTs auf dem Datenträger zu speichern. Das Native-Format wird empfohlen, wenn der UDT einfach ist und nur Felder der folgenden Typen enthält:

bool, byte, sbyte, short, ushort, int, uint, long, ulong, float, double, SqlByte, SqlInt16, SqlInt32, SqlInt64, SqlDateTime, SqlSingle, SqlDouble, SqlMoney, SqlBoolean

Werttypen, die nicht aus den oben genannten Typen bestehen, sind gute Kandidaten für das Native-Format, z. B. structs in Visual C# (oder Structures, wie sie in Visual Basic genannt werden). Ein UDT, der mit dem Native-Serialisierungsformat angegeben wurde, kann z. B. ein Feld eines anderen UDTs enthalten, das auch mit dem Native-Format angegeben wurde. Wenn die UDT-Definition komplexer ist und Datentypen enthält, die nicht aus der Liste oben stammen, müssen Sie stattdessen das UserDefined-Serialisierungsformat angeben.

Für das Native-Format müssen die folgenden Anforderungen erfüllt sein:

  • Der Typ darf für Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.MaxByteSize keinen Wert angeben.

  • Alle Felder müssen serialisierbar sein.

  • System.Runtime.InteropServices.StructLayoutAttribute muss als StructLayout.LayoutKindSequential angegeben werden, wenn der UDT in einer Klasse und nicht in einer Struktur definiert wird. Dieses Attribut steuert das physische Layout der Datenfelder. Außerdem müssen dadurch die Member in der Reihenfolge angeordnet werden, in der sie angezeigt werden. SQL Server verwendet dieses Attribut, um die Feldreihenfolge für UDTs mit mehreren Werten zu bestimmen.

Ein Beispiel für einen UDT, der mit Native-Serialisierung definiert wird, finden Sie im Point-UDT in Programmieren benutzerdefinierter Typen.

UserDefined-Serialisierung

Die UserDefined-Formateinstellung für das Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute-Attribut gibt dem Entwickler volle Kontrolle über das Binärformat. Wenn Sie die Format-Attributeigenschaft als UserDefined angeben, müssen Sie im Code wie folgt vorgehen:

  • Geben Sie die optionale IsByteOrdered-Attributeigenschaft an. Der Standardwert ist false.

  • Geben Sie die MaxByteSize-Eigenschaft von Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute an.

  • Schreiben Sie Code, um die Read- und die Write-Methode für den UDT zu implementieren, indem Sie die System.Data.Sql.IBinarySerialize-Schnittstelle implementieren.

Ein Beispiel für einen UDT, der mit UserDefined-Serialisierung definiert wird, finden Sie im Currency-UDT in Programmieren benutzerdefinierter Typen.

HinweisHinweis

Seit SQL Server 2005 (RTM-Version) dürfen CLR-UDTs mit benutzerdefinierter Serialisierung ihre Felder als Teil nicht permanenter berechneter Spalten oder Sichten indizieren. In diesen Situation kann eine nicht deterministische UDT-Serialisierung/-Deserialisierung zur Indexbeschädigung führen und wurde daher aus SQL Server 2005 SP1 entfernt. In SQL Server 2005 SP1 müssen UDT-Felder die systemeigene Serialisierung verwenden oder erhalten bleiben, um indiziert zu werden. Alle vorhandenen Indizes in UDT-Feldern sollten weiterhin wie zuvor funktionieren.

Serialisierungsattribute

Attribute bestimmen, wie Serialisierung verwendet wird, um die Speicherdarstellung von UDTs zu erstellen und um UDTs durch Werte an den Client zu übertragen. Beim Erstellen des UDTs ist es erforderlich, das Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute anzugeben. Das Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute-Attribut gibt an, dass die Klasse ein UDT ist, und gibt den Speicher für den UDT an. Sie können das Serializable-Attribut optional angeben, obwohl SQL Server dieses nicht erfordert.

Das Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute verfügt über folgende Eigenschaften.

  • Format
    Gibt das Serialisierungsformat an, das je nach den Datentypen des UDTs Native oder UserDefined sein kann.

  • IsByteOrdered
    Ein Boolean-Wert, der bestimmt, wie SQL Server binäre Vergleiche für den UDT durchführt.

  • IsFixedLength
    Gibt an, ob alle Instanzen dieses UDTs dieselbe Länge haben.

  • MaxByteSize
    Die maximale Größe der Instanz in Byte. Sie müssen die MaxByteSize mit dem UserDefined-Serialisierungsformat angeben. Bei einem UDT, für den benutzerdefinierte Serialisierung festgelegt ist, bezieht sich MaxByteSize auf die Gesamtgröße des UDTs in der vom Benutzer festgelegten serialisierten Form. Der Wert von MaxByteSize muss zwischen 1 und 8000 liegen oder auf -1 festgelegt werden, um anzugeben, dass der UDT größer als 8000 Byte ist (die Gesamtgröße kann die maximale LOB-Größe nicht übersteigen). Angenommen, für einen UDT ist eine Zeichenfolge von 10 Zeichen (System.Char) festgelegt. Wenn der UDT anhand eines BinaryWriter serialisiert wird, beträgt die Gesamtgröße der serialisierten Zeichenfolge 22 Byte: 2 Byte pro Unicode-UTF-16-Zeichen, multipliziert mit der maximalen Anzahl von Zeichen, plus 2 Kontrollzeichen, die beim Serialisieren eines binären Datenstroms zusätzlich anfallen. Bei der Ermittlung des MaxByteSize-Werts muss daher die Gesamtgröße des serialisierten UDTs berücksichtigt werden: die Größe der ins Binärformat serialisierten Daten plus die bei der Serialisierung anfallenden Daten.

  • ValidationMethodName
    Der Name der Methode, mit der Instanzen des UDTs überprüft werden.

Einstellung 'IsByteOrdered'

Wenn die Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.IsByteOrdered-Eigenschaft auf true festgelegt wird, gewährleisten Sie damit, dass die serialisierten Binärdaten für eine semantische Sortierung der Informationen verwendet werden können. So kann jede Instanz eines UDT-Objekts mit Bytereihenfolge nur eine einzige serialisierte Darstellung haben. Die Ausführung eines Vergleichsvorgangs für die serialisierten Bytes in SQL Server sollte zu denselben Resultaten führen wie der entsprechende Vergleichsvorgang für verwalteten Code. Die folgenden Funktionen werden ebenfalls unterstützt, wenn IsByteOrdered auf true festgelegt ist:

  • Die Fähigkeit zum Erstellen von Indizes für Spalten dieses Typs

  • Die Fähigkeit, für Spalten dieses Typs Primär- und Fremdschlüssel sowie die Einschränkungen CHECK und UNIQUE zu erstellen

  • Die Fähigkeit, Transact-SQL-ORDER BY-, GROUP BY- und PARTITION BY-Klauseln zu verwenden. In diesen Fällen wird die binäre Darstellung des Typs verwendet, um die Reihenfolge zu bestimmen

  • Die Fähigkeit, Vergleichsoperatoren in Transact-SQL-Anweisungen zu verwenden

  • Die Fähigkeit, berechnete Spalten dieses Typs beizubehalten

Beachten Sie, dass sowohl das Native-Serialisierungsformat als auch das UserDefined-Serialisierungsformat die folgenden Vergleichsoperatoren unterstützen, wenn IsByteOrdered auf true festgelegt ist:

  • Gleich (=)

  • Ungleich (!=)

  • Größer als (>)

  • Kleiner als (<)

  • Größer als oder gleich (>=)

  • Kleiner als oder gleich (<=)

Implementieren von NULL-Zulässigkeit

Zusätzlich zum ordnungsgemäßen Angeben der Attribute für die Assemblys muss die Klasse auch NULL-Zulässigkeit unterstützen. UDTs, die in SQL Server geladen werden, erkennen Nullwerte, aber damit der UDT einen Nullwert erkennt, muss die Klasse die INullable-Schnittstelle implementieren. Weitere Informationen sowie ein Beispiel für das Implementieren von NULL-Zulässigkeit in einem UDT finden Sie unter Programmieren benutzerdefinierter Typen.

Zeichenfolgenkonvertierungen

Zum Unterstützen der Zeichenfolgenkonvertierung in und aus UDTs müssen Sie in der Klasse eine Parse-Methode und eine ToString-Methode angeben. Die Parse-Methode lässt das Konvertieren einer Zeichenfolge in einen UDT zu. Die Zeichenfolge muss als static (oder Shared in Visual Basic) deklariert werden und einen Parameter vom Typ System.Data.SqlTypes.SqlString verwenden. Weitere Informationen sowie ein Beispiel für das Implementieren der Parse-Methode und der ToString-Methode finden Sie unter Programmieren benutzerdefinierter Typen.

XML-Serialisierung

UDTs müssen die Konvertierung in und aus xml-Daten unterstützen, indem sie dem Vertrag für die XML-Serialisierung entsprechen. Der System.Xml.Serialization-Namespace enthält Klassen, die zum Serialisieren von Objekten in Dokumente oder Datenströme im XML-Format verwendet werden. Sie können die xml-Serialisierung mithilfe der IXmlSerializable-Schnittstelle implementieren, die das benutzerdefinierte Formatieren für die XML-Serialisierung und -Deserialisierung bereitstellt.

Zusätzlich zum Durchführen expliziter Konvertierungen von UDT in xml ermöglicht die XML-Serialisierung Folgendes:

  • Verwenden von Xquery für Werte von UDT-Instanzen nach der Konvertierung in den xml-Datentyp.

  • Verwenden von UDTs in parametrisierten Abfragen und Webmethoden mit systemeigenen XML-Webdiensten in SQL Server. Weitere Informationen finden Sie unter Verarbeiten des xml-Datentyps und CLR-benutzerdefinierter Datentypen.

  • Verwenden von UDTs, um ein Massenladen von XML-Daten durchzuführen.

  • Serialisieren von DataSets, die Tabellen mit UDT-Spalten enthalten.

UDTs werden nicht in FOR XML-Abfragen serialisiert. Um eine FOR XML-Abfrage auszuführen, die die XML-Serialisierung von UDTs anzeigt, konvertieren Sie die einzelnen UDT-Spalten explizit in den xml-Datentyp in der SELECT-Anweisung. Sie können die Spalten auch explizit in varbinary, varchar oder nvarchar konvertieren.

Siehe auch

Andere Ressourcen