Creazione di tipi definiti dall'utente - Requisiti

Si applica a:SQL Server

È necessario prendere diverse decisioni importanti sulla progettazione durante la creazione di un tipo definito dall'utente (UDT) da installare in Microsoft SQL Server. Benché nella maggior parte dei casi sia consigliabile creare il tipo definito dall'utente come struttura, la creazione come classe rappresenta un'altra opzione valida. La definizione UDT deve essere conforme alle specifiche per la creazione di UDT per poter essere registrata con SQL Server.

Requisiti per l'implementazione di tipi definiti dall'utente

Per l'esecuzione in SQL Server, l'UDT deve implementare i requisiti seguenti nella definizione UDT:

L'UDT deve specificare Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute. L'uso di System.SerializableAttribute è facoltativo, ma consigliato.

  • L'UDT deve implementare l'interfaccia System.Data.SqlTypes.INullable nella classe o nella struttura creando un metodo statico pubblico (condiviso in Microsoft Visual Basic) Null . SQL Server è con riconoscimento null per impostazione predefinita. Questa condizione è necessaria affinché il codice in esecuzione nel tipo definito dall'utente sia in grado di riconoscere un valore Null.

  • L'UDT deve contenere un metodo parse statico pubblico (o condiviso) che supporta l'analisi da e un metodo ToString pubblico per la conversione in una rappresentazione stringa dell'oggetto.

  • Un oggetto UDT con un formato di serializzazione definito dall'utente deve implementare l'interfaccia System.Data.IBinarySerialize e fornire un metodo Read e Write .

  • L'UUDT deve implementare System.Xml. Serialization.IXmlSerializable o tutte le proprietà e i campi pubblici devono essere di tipi serializzabili o decorati con l'attributo XmlIgnore se è necessaria l'override della serializzazione standard.

  • È necessario che sia presente solo una serializzazione di un oggetto del tipo definito dall'utente. La convalida ha esito negativo se le routine di serializzazione e deserializzazione riconoscono più di una rappresentazione di un oggetto specifico.

  • SqlUserDefinedTypeAttribute.IsByteOrdered deve essere true per confrontare i dati in ordine di byte. Se l'interfaccia IComparable non è implementata e SqlUserDefinedTypeAttribute.IsByteOrdered è false, i confronti degli ordini di byte avranno esito negativo.

  • Un tipo definito dall'utente specificato in una classe deve disporre di un costruttore pubblico che non accetta argomenti. È eventualmente possibile creare costruttori di classe di overload aggiuntivi.

  • Il tipo definito dall'utente deve esporre elementi dati come campi pubblici o routine di proprietà.

  • I nomi pubblici non possono essere più di 128 caratteri e devono essere conformi alle regole di denominazione SQL Server per gli identificatori definiti in Identificatori di database.

  • sql_variant colonne non possono contenere istanze di un oggetto UDT.

  • I membri ereditati non sono accessibili da Transact-SQL perché il sistema di tipi di SQL Server non è a conoscenza della gerarchia di ereditarietà tra le UDT. È tuttavia possibile utilizzare l'ereditarietà quando si strutturano le classi ed è possibile chiamare tali metodi nell'implementazione di codice gestito del tipo.

  • Non è possibile eseguire l'overload dei membri, ad eccezione del costruttore della classe. Se si crea un metodo di overload, non viene generato alcun errore quando si registra l'assembly o si crea il tipo in SQL Server. Il rilevamento del metodo di overload si verifica in fase di esecuzione e non durante la creazione del tipo. Nella classe possono essere presenti metodi di overload, a condizione che non vengano mai richiamati. Quando si richiama il metodo di overload, viene generato un errore.

  • Tutti i membri statici (o condivisi) devono essere dichiarati come costanti o come sola lettura. I membri statici non possono essere modificati.

  • Se il campo SqlUserDefinedTypeAttribute.MaxByteSize è impostato su -1, è possibile che il numero di dimensioni dell'oggetto di grandi dimensioni (LOB) sia serializzato (attualmente 2 GB). Le dimensioni dell'UDT non possono superare il valore specificato nel campo MaxByteSized .

Nota

Anche se non viene usato dal server per eseguire confronti, è possibile implementare facoltativamente l'interfaccia System.IComparable , che espone un singolo metodo, CompareTo. Tale metodo viene utilizzato sul lato client in situazioni in cui è preferibile confrontare o ordinare in modo accurato i valori del tipo definito dall'utente.

Serializzazione nativa

La scelta degli attributi di serializzazione corretti per il tipo definito dall'utente dipende dal tipo definito dall'utente che si desidera creare. Il formato di serializzazione nativa usa una struttura molto semplice che consente SQL Server di archiviare una rappresentazione nativa efficiente dell'UDT su disco. Il formato nativo è consigliato se l'UUDT è semplice e contiene solo campi dei tipi seguenti:

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

I tipi di valore costituiti da campi dei tipi precedenti sono validi per il formato nativo , ad esempio gli struct in Visual C#, (o Strutture noti in Visual Basic). Ad esempio, un'UDT specificata con il formato di serializzazione nativa può contenere un campo di un altro UDT specificato anche con il formato Nativo . Se la definizione UDT è più complessa e contiene tipi di dati non presenti nell'elenco precedente, è necessario specificare invece il formato di serializzazione UserDefined .

Il formato Nativo presenta i requisiti seguenti:

  • Il tipo non deve specificare un valore per Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.MaxByteSize.

  • Tutti i campi devono essere serializzabili.

  • L'attributo System.Runtime.InteropServices.StructLayoutAttribute deve essere specificato come StructLayout.LayoutKindSequential se l'UDT è definito in una classe e non in una struttura. Questo attributo controlla il layout fisico dei campi dati e viene utilizzato per forzare la disposizione dei membri in base all'ordine in cui vengono visualizzati. SQL Server usa questo attributo per determinare l'ordine di campo per le UDT con più valori.

Per un esempio di UDT definito con serializzazione nativa , vedere point UDT in Codifica User-Defined tipi.

Serializzazione UserDefined

L'impostazione del formato UserDefined per l'attributo Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute fornisce allo sviluppatore il controllo completo sul formato binario. Quando si specifica la proprietà Attributo Format come UserDefined, è necessario eseguire le operazioni seguenti nel codice:

  • Specificare la proprietà dell'attributo IsByteOrdered facoltativa . Il valore predefinito è false.

  • Specificare la proprietà MaxByteSize di Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.

  • Scrivere codice per implementare metodi di lettura e scrittura per l'utente tramite l'implementazione dell'interfaccia System.Data.Sql.IBinarySerialize .

Per un esempio di UDT definito con la serializzazione UserDefined , vedere Valuta UDT in Codifica User-Defined Tipi.

Nota

Ai fini dell'indicizzazione, i campi con tipo definito dall'utente devono utilizzare la serializzazione nativa o essere resi persistenti.

Attributi di serializzazione

Gli attributi consentono di determinare la modalità di utilizzo della serializzazione per costruire la rappresentazione di archiviazione dei tipi definiti dall'utente e per trasmettere tali tipi al client in base al valore. È necessario specificare Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute durante la creazione dell'UDT. L'attributo Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute indica che la classe è un'UDT e specifica l'archiviazione per l'UDT. Facoltativamente, è possibile specificare l'attributo Serializable, anche se SQL Server non richiede questa operazione.

Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute include le proprietà seguenti.

Formato
Specifica il formato di serializzazione, che può essere Nativo o UserDefined, a seconda dei tipi di dati dell'UDT.

IsByteOrdered
Valore booleano che determina il modo in cui SQL Server esegue confronti binari nell'UDT.

IsFixedLength
Indica se tutte le istanze del tipo definito dall'utente sono della stessa lunghezza.

MaxByteSize
Dimensioni massime, in byte, dell'istanza. È necessario specificare MaxByteSize con il formato di serializzazione UserDefined . Per un oggetto UDT con serializzazione definita dall'utente specificato, MaxByteSize fa riferimento alle dimensioni totali dell'UDT nel formato serializzato definito dall'utente. Il valore di MaxByteSize deve essere compreso nell'intervallo compreso tra 1 e 8000 oppure impostato su -1 per indicare che l'UUDT è maggiore di 8000 byte (la dimensione totale non può superare la dimensione massima del LOB). Si consideri un oggetto UDT con una proprietà di una stringa di 10 caratteri (System.Char). Quando il tipo definito dall'utente viene serializzato utilizzando un oggetto BinaryWriter, le dimensioni totali della stringa serializzata sono pari a 22 byte per ciascun carattere Unicode UTF-16, moltiplicati per il numero massimo di caratteri, più 2 byte di controllo per l'overhead generato dalla serializzazione di un flusso binario. Pertanto, quando si determina il valore di MaxByteSize, è necessario considerare le dimensioni totali dell'UDT serializzato: le dimensioni dei dati serializzati in formato binario e il sovraccarico in base alla serializzazione.

ValidationMethodName
Nome del metodo utilizzato per convalidare le istanze del tipo definito dall'utente.

Impostazione di IsByteOrdered

Quando la proprietà Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.IsByteOrdered è impostata su true, si garantisce che i dati binari serializzati possano essere usati per l'ordinamento semantico delle informazioni. In questo modo, ogni istanza di un oggetto del tipo definito dall'utente ordinato per byte può disporre di una sola rappresentazione serializzata. Quando viene eseguita un'operazione di confronto in SQL Server nei byte serializzati, i risultati devono essere uguali a se la stessa operazione di confronto è stata eseguita nel codice gestito. Le funzionalità seguenti sono supportate anche quando IsByteOrdered è impostato su true:

  • Capacità di creare indici nelle colonne di questo tipo.

  • Capacità di creare chiavi primarie ed esterne, nonché vincoli CHECK e UNIQUE sulle colonne di questo tipo.

  • Possibilità di usare clausole Transact-SQL ORDER BY, GROUP BY e PARTITION BY. In questi casi, per determinare l'ordine viene utilizzata la rappresentazione binaria del tipo.

  • Possibilità di usare gli operatori di confronto nelle istruzioni Transact-SQL.

  • Capacità di garantire la persistenza delle colonne calcolate di questo tipo.

Si noti che sia i formati di serializzazione Native che UserDefined supportano gli operatori di confronto seguenti quando IsByteOrdered è impostato su true:

  • Uguale a (=)

  • Diverso da (!=)

  • Maggiore di (>)

  • Minore di (<)

  • Maggiore o uguale a (>=)

  • Minore o uguale a (<=)

Implementazione del supporto dei valori Null

Oltre a specificare correttamente gli attributi per gli assembly, la classe deve inoltre supportare i valori Null. I tipi definiti dall'utente caricati in SQL Server sono in grado di riconoscere null, ma affinché il tipo definito dall'utente riconosca un valore Null, la classe deve implementare l'interfaccia INullable. Per altre informazioni e un esempio di come implementare il supporto dei valori Null in un tipo definito dall'utente, vedere Codifica di tipi di User-Defined.

Conversioni di stringhe

Per supportare la conversione di stringhe da e verso il tipo definito dall'utente, è necessario fornire un metodo Parse e un metodo ToString nella classe. Il metodo Parse consente di convertire una stringa in un tipo definito dall'utente. Deve essere dichiarato come statico (o Condiviso in Visual Basic) e accettare un parametro di tipo System.Data.SqlTypes.SqlString. Per altre informazioni e un esempio di come implementare i metodi Parse e ToString , vedere Codifica di tipi User-Defined.

Serializzazione XML

I tipi definiti dall'utente devono supportare la conversione da e verso il tipo di dati xml conforme al contratto per la serializzazione XML. System.Xml . Lo spazio dei nomi di serializzazione contiene classi utilizzate per serializzare gli oggetti in documenti o flussi in formato XML. È possibile scegliere di implementare la serializzazione xml usando l'interfaccia IXmlSerializable , che fornisce formattazione personalizzata per la serializzazione XML e la deserializzazione.

Oltre a eseguire conversioni esplicite da UDT a xml, la serializzazione XML consente di:

  • Usare Xquery sui valori delle istanze del tipo definito dall'utente dopo la conversione nel tipo di dati xml .

  • Usare tipi definiti dall'utente nelle query con parametri e nei metodi Web con Servizi Web XML nativi in SQL Server.

  • Utilizzare i tipi definiti dall'utente per ricevere un caricamento bulk di dati XML.

  • Serializzare set di dati che contengono tabelle con colonne del tipo definito dall'utente.

I tipi definiti dall'utente non vengono serializzati nelle query FOR XML. Per eseguire una query FOR XML che visualizza la serializzazione XML dei tipi definiti dall'utente, convertire in modo esplicito ogni colonna UDT nel tipo di dati xml nell'istruzione SELECT. È anche possibile convertire in modo esplicito le colonne in varbinary, varchar o nvarchar.

Vedere anche

Creazione di un tipo di User-Defined