Partilhar via


Criar tipos definidos pelo usuário – Requisitos

Aplica-se a: SQL Server

Você deve tomar várias decisões importantes de design ao criar um UDT (tipo definido pelo usuário) a ser instalado no Microsoft SQL Server. De uma forma geral, é recomendável criar o UDT como uma estrutura, embora criá-lo como classe também seja uma opção. A definição de UDT deve estar em conformidade com as especificações para a criação de UDTs para que ela seja registrada no SQL Server.

Requisitos para implementação de UDTs

Para ser executado no SQL Server, o UDT deve implementar os seguintes requisitos na definição do UDT:

O UDT deve especificar o Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute. O uso do System.SerializableAttribute é opcional, mas recomendado.

  • O UDT deve implementar a interface System.Data.SqlTypes.INullable na classe ou estrutura criando um método Null estático público (Compartilhado no Microsoft Visual Basic). O SQL Server tem reconhecimento de nulo por padrão. Isso é necessário para que o código executado no UDT consiga reconhecer um valor nulo.

  • O UDT deve conter um método Parse estático público (ou compartilhado) que dê suporte à análise de e um método ToString público para converter em uma representação de cadeia de caracteres do objeto.

  • Um UDT com um formato de serialização definido pelo usuário deve implementar a interface System.Data.IBinarySerialize e fornecer um método Read e Write.

  • O UDT deve implementar System.Xml.Serialization.IXmlSerializable, ou todos os campos e propriedades públicos devem ser de tipos serializáveis XML ou decorados com o atributo XmlIgnore se a substituição da serialização padrão for necessária.

  • Deve haver apenas uma serialização de um objeto UDT. Haverá falha na validação se as rotinas de serialização ou desserialização reconhecerem mais de uma representação de um objeto específico.

  • SqlUserDefinedTypeAttribute.IsByteOrdered deve ser true para comparar dados em ordem de bytes. Se a interface IComparable não for implementada e SqlUserDefinedTypeAttribute.IsByteOrdered for false, as comparações de ordem de bytes falharão.

  • Um UDT definido em uma classe deve ter um construtor público que não leve argumentos. Você tem a opção de criar construtores de classe sobrecarregados adicionais.

  • O UDT precisa expor elementos de dados como campos públicos ou procedimentos de propriedade.

  • Os nomes públicos não podem ter mais de 128 caracteres e devem estar em conformidade com as regras de nomenclatura do SQL Server para identificadores, conforme definido em Identificadores de Banco de Dados.

  • sql_variant colunas não podem conter instâncias de um UDT.

  • Os membros herdados não podem ser acessados do Transact-SQL porque o sistema de tipos do SQL Server não está ciente da hierarquia de herança entre os UDTs. Entretanto, você pode usar a herança ao estruturar suas classes, além de chamar esses métodos na implementação de código gerenciado do tipo.

  • Os membros não podem ficar sobrecarregados, com exceção do construtor de classe. Se você criar um método sobrecarregado, nenhum erro será gerado quando você registrar o assembly ou criar o tipo no SQL Server. A detecção do método sobrecarregado ocorre em tempo de execução, e não quando o tipo é criado. Os métodos sobrecarregados podem existir na classe, contanto que nunca sejam invocados. Quando você invoca o método sobrecarregado, ocorre um erro.

  • Todos os membros estáticos (ou compartilhados) devem ser declarados como constantes ou como somente leitura. Membros estáticos não podem ser mutáveis.

  • Se o campo SqlUserDefinedTypeAttribute.MaxByteSize for definido como -1, o UDT serializado poderá ser tão grande quanto o limite de tamanho de LOB (objeto grande) (atualmente 2 GB). O tamanho do UDT não pode exceder o valor especificado no campo MaxByteSized .

Observação

Embora não seja usado pelo servidor para realizar comparações, você pode, opcionalmente, implementar a interface System.IComparable , que expõe um único método, CompareTo. Isso é usado no lado do cliente em situações nas quais é desejável comparar ou ordenar valores UDT com precisão.

Serialização nativa

A escolha dos atributos de serialização adequados para o UDT depende do tipo de UDT que você está tentando criar. O formato de serialização nativa utiliza uma estrutura muito simples que permite que o SQL Server armazene uma representação nativa eficiente do UDT no disco. O formato Nativo é recomendado se o UDT for simples e contiver apenas campos dos seguintes tipos:

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

Os tipos de valor compostos por campos dos tipos acima são bons candidatos para o formato nativo , como structs no Visual C# (ou Structures , como são conhecidos no Visual Basic). Por exemplo, um UDT especificado com o formato de serialização Nativo pode conter um campo de outro UDT que também foi especificado com o formato Nativo . Se a definição de UDT for mais complexa e contiver tipos de dados que não estão na lista acima, você deverá especificar o formato de serialização UserDefined .

O formato Nativo tem os seguintes requisitos:

  • O tipo não deve especificar um valor para Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.MaxByteSize.

  • Todos os campos precisam ser serializáveis.

  • O System.Runtime.InteropServices.StructLayoutAttribute deve ser especificado como StructLayout.LayoutKindSequential se o UDT for definido em uma classe e não em uma estrutura. Esse atributo controla o layout físico dos campos de dados e é usado para obrigar os membros a ser dispostos na ordem em que aparecem. O SQL Server usa esse atributo para determinar a ordem dos campos para UDTs com vários valores.

Para obter um exemplo de um UDT definido com serialização nativa , consulte o UDT de ponto em Codificação de tipos definidos pelo usuário.

Serialização UserDefined

A configuração de formato UserDefined para o atributo Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute dá ao desenvolvedor controle total sobre o formato binário. Ao especificar a propriedade de atributo Format como UserDefined, você deve fazer o seguinte em seu código:

  • Especifique a propriedade de atributo opcional IsByteOrdered . O valor padrão é falso.

  • Especifique a propriedade MaxByteSize do Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.

  • Escreva código para implementar métodos de leitura e gravação para o UDT implementando a interface System.Data.Sql.IBinarySerialize .

Para obter um exemplo de um UDT definido com serialização UserDefined , consulte o UDT de moeda em Codificação de tipos definidos pelo usuário.

Observação

Os campos UDT precisam usar serialização nativa ou serem persistidos para serem indexados.

Atributos de serialização

Os atributos determinam como a serialização é usada para construir a representação de armazenamento de UDTs e transmiti-los por valor para o cliente. Você deve especificar o Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute ao criar o UDT. O atributo Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute indica que a classe é um UDT e especifica o armazenamento para o UDT. Opcionalmente, você pode especificar o atributo Serializable, embora o SQL Server não exija isso.

O Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute tem as propriedades a seguir.

Formato
Especifica o formato de serialização, que pode ser Nativo ou UserDefined, dependendo dos tipos de dados do UDT.

IsByteOrdered
Um valor booliano que determina como o SQL Server executa comparações binárias no UDT.

IsFixedLength
Indica se todas as instâncias desse UDT têm a mesma extensão.

MaxByteSize
O tamanho máximo da instância, em bytes. Você deve especificar MaxByteSize com o formato de serialização UserDefined . Para um UDT com serialização definida pelo usuário especificada, MaxByteSize refere-se ao tamanho total do UDT em sua forma serializada, conforme definido pelo usuário. O valor de MaxByteSize deve estar no intervalo de 1 a 8000 ou definido como -1 para indicar que o UDT é maior que 8000 bytes (o tamanho total não pode exceder o tamanho máximo de LOB). Considere um UDT com uma propriedade de uma cadeia de caracteres de 10 caracteres (System.Char). Quando o UDT é serializado usando um BinaryWriter, o tamanho total da cadeia de caracteres serializada é de 22 bytes: 2 bytes por caractere Unicode UTF-16, multiplicados pelo número máximo de caracteres, mais 2 bytes de controle da sobrecarga ocasionada pela serialização de um fluxo binário. Portanto, ao determinar o valor de MaxByteSize, o tamanho total do UDT serializado deve ser considerado: o tamanho dos dados serializados em formato binário mais a sobrecarga incorrida pela serialização.

ValidationMethodName
O nome do método usado para validar instâncias do UDT.

Definindo IsByteOrdered

Quando a propriedade Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.IsByteOrdered é definida como true, você está, na verdade, garantindo que os dados binários serializados possam ser usados para ordenação semântica das informações. Assim, cada instância de um objeto UDT ordenado por byte pode ter somente uma representação serializada. Quando uma operação de comparação é executada no SQL Server nos bytes serializados, seus resultados devem ser os mesmos como se a mesma operação de comparação tivesse ocorrido no código gerenciado. Os seguintes recursos também têm suporte quando IsByteOrdered é definido como true:

  • A capacidade de criar índices em colunas desse tipo.

  • A capacidade de criar chaves primárias e estrangeiras, além de restrições CHECK e UNIQUE em colunas desse tipo.

  • A capacidade de usar as cláusulas Transact-SQL ORDER BY, GROUP BY e PARTITION BY. Nesses casos, a representação binária do tipo é usada para determinar a ordem.

  • A capacidade de usar operadores de comparação em instruções Transact-SQL.

  • A capacidade de persistir colunas computadas desse tipo.

Observe que os formatos de serialização Native e UserDefined dão suporte aos seguintes operadores de comparação quando IsByteOrdered é definido como true:

  • Igual a (=)

  • Diferente de (!=)

  • Maior que (>)

  • Menor que (<)

  • Maior que ou igual a (>=)

  • Menor que ou igual a (<=)

Implementando a nulidade

Além de especificar corretamente os atributos dos assemblies, sua classe também precisa suportar a nulidade. Os UDTs carregados no SQL Server reconhecem nulo, mas para que o UDT reconheça um valor nulo, a classe deve implementar a interface INullable . Para obter mais informações e um exemplo de como implementar a nulidade em um UDT, consulte Codificando tipos definidos pelo usuário.

Conversões de cadeia de caracteres

Para dar suporte à conversão de cadeia de caracteres de e para o UDT, você deve fornecer um método Parse e um método ToString em sua classe. O método Parse permite que uma cadeia de caracteres seja convertida em um UDT. Ele deve ser declarado como estático (ou compartilhado no Visual Basic) e usar um parâmetro do tipo System.Data.SqlTypes.SqlString. Para obter mais informações e um exemplo de como implementar os métodos Parse e ToString , consulte Codificando tipos definidos pelo usuário.

Serialização XML

Os UDTs devem dar suporte à conversão de e para o tipo de dados xml em conformidade com o contrato de serialização XML. O namespace System.Xml.Serialization contém classes que são usadas para serializar objetos em documentos ou fluxos no formato XML. Você pode optar por implementar a serialização xml usando a interface IXmlSerializable , que fornece formatação personalizada para serialização e desserialização XML.

Além de executar conversões explícitas de UDT para xml, a serialização XML permite:

  • Use o Xquery sobre valores de instâncias UDT após a conversão para o tipo de dados xml .

  • Use UDTs em consultas parametrizadas e métodos Web com XML Web Services nativos no SQL Server.

  • Usar UDTs para receber um carregamento em massa de dados XML.

  • Serializar DataSets que contêm tabelas com colunas de UDT.

Os UDTs não são serializados em consultas FOR XML. Para executar uma consulta FOR XML que exiba a serialização XML de UDTs, converta explicitamente cada coluna UDT no tipo de dados xml na instrução SELECT. Você também pode converter explicitamente as colunas em varbinary, varchar ou nvarchar.

Confira também

Criando um tipo definido pelo usuário