Création de types définis par l’utilisateur - Exigences

S’applique à :SQL Server

Vous devez prendre plusieurs décisions de conception importantes lors de la création d’un type défini par l’utilisateur (UDT) à installer dans Microsoft SQL Server. Pour la plupart des types définis par l'utilisateur, il est recommandé de créer un type défini par l'utilisateur sous forme de structure mais il est également possible de le créer sous forme de classe. La définition UDT doit être conforme aux spécifications de création de types définis par l’utilisateur pour qu’elle soit enregistrée auprès de SQL Server.

Configuration requise pour l'implémentation des types définis par l'utilisateur

Pour s’exécuter dans SQL Server, votre type défini par l’utilisateur doit implémenter les exigences suivantes dans la définition UDT :

L’UDT doit spécifier l’attribut Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute. L’utilisation de System.SerializableAttribute est facultative, mais recommandée.

  • L’UDT doit implémenter l’interface System.Data.SqlTypes.INullable dans la classe ou la structure en créant une méthode Null statique publique (partagée dans Microsoft Visual Basic). SQL Server prend en compte la valeur Null par défaut. Ceci est nécessaire pour que le code exécuté dans l'UDT puisse être en mesure de reconnaître une valeur NULL.

  • L’UDT doit contenir une méthode d’analysestatique (ou partagée) publique qui prend en charge l’analyse à partir de et une méthode ToString publique pour la conversion en une représentation sous forme de chaîne de l’objet.

  • Un type défini par l’utilisateur avec un format de sérialisation défini par l’utilisateur doit implémenter l’interface System.Data.IBinarySerialize et fournir une méthode Read et Write .

  • L’UDT doit implémenter System.Xml. Serialization.IXmlSerializable, ou tous les champs et propriétés publics doivent être de types sérialisables XML ou décorés avec l’attribut XmlIgnore si la substitution de la sérialisation standard est nécessaire.

  • Chaque objet UDT doit être soumis à une seule sérialisation. La validation échoue si les routines de sérialisation ou désérialisation reconnaissent plusieurs représentations d'un objet en particulier.

  • SqlUserDefinedTypeAttribute.IsByteOrdered doit avoir la valeur true pour comparer les données dans l’ordre d’octets. Si l’interface IComparable n’est pas implémentée et que SqlUserDefinedTypeAttribute.IsByteOrdered a la valeur false, les comparaisons d’ordre d’octets échouent.

  • Un UDT défini dans une classe doit disposer d'un constructeur public qui n'accepte aucun argument. Vous pouvez éventuellement créer des constructeurs de classe surchargés supplémentaires.

  • L'UDT doit dévoiler les éléments de données sous forme de champs publics ou de procédures de propriété.

  • Les noms publics ne peuvent pas contenir plus de 128 caractères et doivent être conformes aux règles de nommage SQL Server pour les identificateurs tels que définis dans Identificateurs de base de données.

  • sql_variant colonnes ne peuvent pas contenir d’instances d’un type défini par l’utilisateur.

  • Les membres hérités ne sont pas accessibles à partir de Transact-SQL, car le système de type SQL Server n’a pas connaissance de la hiérarchie d’héritage entre les types définis par l’utilisateur. Toutefois, vous pouvez recourir à la fonction d'héritage au moment de structurer vos classes et pouvez appeler ces méthodes dans l'implémentation du code managé du type.

  • Hormis le constructeur de classe, les membres ne peuvent pas être surchargés. Si vous créez une méthode surchargée, aucune erreur n’est générée lorsque vous inscrivez l’assembly ou créez le type dans SQL Server. La détection de la méthode surchargée a lieu au moment de l'exécution et non lors de la création du type. Les méthodes surchargées peuvent exister dans la classe tant qu'elles ne sont jamais appelées. Une erreur est générée dès que vous appelez la méthode surchargée.

  • Tous les membres statiques (ou partagés) doivent être déclarés en tant que constantes ou en lecture seule. Les membres statiques ne peuvent pas être mutables.

  • Si le champ SqlUserDefinedTypeAttribute.MaxByteSize est défini sur -1, l’UDT sérialisé peut être aussi grand que la limite de taille DOB (objet volumineux) (actuellement 2 Go). La taille de l’UDT ne peut pas dépasser la valeur spécifiée dans le champ MaxByteSized .

Notes

Bien qu’il ne soit pas utilisé par le serveur pour effectuer des comparaisons, vous pouvez éventuellement implémenter l’interface System.IComparable , qui expose une méthode unique, CompareTo. Elle intervient côté client dans des situations où il est préférable de comparer ou de classer avec précision des valeurs de type défini par l'utilisateur (UDT).

Sérialisation native

Le choix du bon attribut de sérialisation pour votre UDT dépend du type d'UDT que vous essayez de créer. Le format de sérialisation native utilise une structure très simple qui permet SQL Server de stocker une représentation native efficace du type défini par l’utilisateur sur le disque. Le format natif est recommandé si l’UDT est simple et contient uniquement des champs des types suivants :

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

Les types valeur composés de champs des types ci-dessus sont de bons candidats pour le format natif , tels que les structs en Visual C# (ou structures telles qu’elles sont connues dans Visual Basic). Par exemple, un type défini par l’utilisateur spécifié avec le format de sérialisation native peut contenir un champ d’un autre type défini par l’utilisateur qui a également été spécifié avec le format natif . Si la définition UDT est plus complexe et contient des types de données qui ne figure pas dans la liste ci-dessus, vous devez spécifier le format de sérialisation UserDefined à la place.

Le format natif présente les exigences suivantes :

  • Le type ne doit pas spécifier de valeur pour Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.MaxByteSize.

  • Tous les champs doivent être sérialisables.

  • System.Runtime.InteropServices.StructLayoutAttribute doit être spécifié en tant que StructLayout.LayoutKindSequential si l’UDT est défini dans une classe et non dans une structure. Cet attribut contrôle la disposition physique des champs de données et est utilisé pour contraindre les membres à se placer dans l'ordre dans lequel ils apparaissent. SQL Server utilise cet attribut pour déterminer l’ordre de champ pour les types définis par l’utilisateur avec plusieurs valeurs.

Pour obtenir un exemple d’un type défini par l’utilisateur avec la sérialisation native , consultez le type défini par l’utilisateur point dans codage User-Defined types.

Sérialisation UserDefined

Le paramètre de format UserDefined pour l’attribut Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute donne au développeur un contrôle total sur le format binaire. Lorsque vous spécifiez la propriété d’attribut Format comme UserDefined, vous devez effectuer les opérations suivantes dans votre code :

  • Spécifiez la propriété d’attribut IsByteOrdered facultative. La valeur par défaut est false.

  • Spécifiez la propriété MaxByteSize de Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.

  • Écrivez du code pour implémenter des méthodes Read et Write pour l’UDT en implémentant l’interface System.Data.Sql.IBinarySerialize .

Pour obtenir un exemple d’un type défini par l’utilisateur avec la sérialisation UserDefined , consultez l’UDT monétaire dans codage User-Defined types.

Notes

Les champs UDT doivent utiliser la sérialisation native ou être persistants pour pouvoir être indexés.

Attributs de sérialisation

Les attributs déterminent la façon dont la sérialisation est utilisée pour construire la représentation de stockage des types définis par l'utilisateur et pour transmettre des types définis par l'utilisateur par valeur au client. Vous devez spécifier l’attribut Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute lors de la création de l’UDT. L’attribut Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute indique que la classe est un UDT et spécifie le stockage pour l’UDT. Vous pouvez éventuellement spécifier l’attribut Serializable, bien que SQL Server ne l’exige pas.

Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute a les propriétés suivantes.

Format
Spécifie le format de sérialisation, qui peut être Natif ou UserDefined, en fonction des types de données de l’UDT.

IsByteOrdered
Valeur booléenne qui détermine comment SQL Server effectue des comparaisons binaires sur l’UDT.

IsFixedLength
Indique si toutes les instances de cet UDT ont la même longueur.

MaxByteSize
Taille maximale de l'instance, en octets. Vous devez spécifier MaxByteSize avec le format de sérialisation UserDefined . Pour un type défini par l’utilisateur avec une sérialisation définie par l’utilisateur spécifiée, MaxByteSize fait référence à la taille totale du type défini par l’utilisateur dans sa forme sérialisée. La valeur de MaxByteSize doit être comprise entre 1 et 8 000, ou définie sur -1 pour indiquer que le type défini par l’utilisateur est supérieur à 8 000 octets (la taille totale ne peut pas dépasser la taille métier maximale). Prenons l’exemple d’un type défini par l’utilisateur avec une propriété d’une chaîne de 10 caractères (System.Char). Lorsque l'UDT est sérialisé à l'aide de BinaryWriter, la taille totale de la chaîne sérialisée est de 22 octets : 2 octets par caractère Unicode UTF-16, multipliés par le nombre maximal de caractères, plus 2 octets de contrôle de la charge mémoire générée par la sérialisation d'un flux binaire. Par conséquent, lors de la détermination de la valeur de MaxByteSize, la taille totale du type défini par l’utilisateur sérialisé doit être prise en compte : la taille des données sérialisées sous forme binaire plus la surcharge occasionnée par la sérialisation.

ValidationMethodName
Nom de la méthode utilisée pour valider des instances du type défini par l'utilisateur.

Définition de la propriété IsByteOrdered

Lorsque la propriété Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.IsByteOrdered a la valeur true, vous garantissez en effet que les données binaires sérialisées peuvent être utilisées pour l’ordre sémantique des informations. Par conséquent, chaque instance d'un objet UDT ordonné par octet peut avoir une seule représentation sérialisée. Lorsqu’une opération de comparaison est effectuée dans SQL Server sur les octets sérialisés, ses résultats doivent être les mêmes que si la même opération de comparaison avait eu lieu dans du code managé. Les fonctionnalités suivantes sont également prises en charge lorsque IsByteOrdered a la valeur true :

  • Possibilité de créer des index dans les colonnes de ce type.

  • Possibilité de créer des clés primaires et étrangères ainsi que des contraintes CHECK et UNIQUE dans les colonnes de ce type.

  • Possibilité d’utiliser les clauses Transact-SQL ORDER BY, GROUP BY et PARTITION BY. Dans ces cas, la représentation binaire du type est utilisée pour déterminer l'ordre.

  • Possibilité d’utiliser des opérateurs de comparaison dans des instructions Transact-SQL.

  • Possibilité de rendre persistantes des colonnes calculées de ce type.

Notez que les formats de sérialisation Native et UserDefined prennent en charge les opérateurs de comparaison suivants lorsque IsByteOrdered a la valeur true :

  • Égal à (=)

  • Différent de (!=)

  • Supérieur à (>)

  • Inférieur à (<)

  • Supérieur ou égal à (>=)

  • Inférieur ou égal à (<=)

Implémentation de la possibilité de valeur NULL

En plus de spécifier correctement les attributs de vos assemblys, votre classe doit également prendre en charge la possibilité de valeur NULL. Les UDT chargés dans SQL Server prennent en charge la valeur Null, mais pour que l’UDT reconnaisse une valeur null, la classe doit implémenter l’interface INullable. Pour plus d’informations et un exemple d’implémentation de la nullabilité dans un UDT, consultez Codage User-Defined types.

Conversions de chaînes

Pour prendre en charge la conversion de chaîne vers et à partir de l’UDT, vous devez fournir une méthode Parse et une méthode ToString dans votre classe. La méthode Parse permet de convertir une chaîne en un UDT. Il doit être déclaré statique (ou partagé en Visual Basic) et prendre un paramètre de type System.Data.SqlTypes.SqlString. Pour plus d’informations et un exemple d’implémentation des méthodes Parse et ToString , consultez Codage User-Defined types.

Sérialisation XML

Les UDT doivent prendre en charge la conversion vers et à partir du type de données xml en se conformant au contrat de sérialisation XML. System.Xml. L’espace de noms de sérialisation contient des classes utilisées pour sérialiser des objets dans des documents ou des flux au format XML. Vous pouvez choisir d’implémenter la sérialisation xml à l’aide de l’interface IXmlSerializable , qui fournit une mise en forme personnalisée pour la sérialisation et la désérialisation XML.

En plus d’effectuer des conversions explicites d’UDT en xml, la sérialisation XML vous permet de :

  • Utilisez Xquery sur les valeurs des instances UDT après la conversion en type de données xml .

  • Utilisez des UDT dans les requêtes paramétrables et les méthodes Web avec les services Web XML natifs dans SQL Server.

  • Utiliser des UDT pour recevoir un chargement en masse de données XML.

  • Sérialiser des datasets contenant des tables avec des colonnes UDT.

Les UDT ne sont pas sérialisés dans les requêtes FOR XML. Pour exécuter une requête FOR XML qui affiche la sérialisation XML des UDT, convertissez explicitement chaque colonne UDT en type de données xml dans l’instruction SELECT. Vous pouvez également convertir explicitement les colonnes en varbinary, varchar ou nvarchar.

Voir aussi

Création d’un type User-Defined