Creazione di tipi definiti dall'utente - Requisiti
Si applica a: SQL Server
È necessario prendere diverse decisioni di progettazione importanti durante la creazione di un tipo definito dall'utente (UDT) da installare in Microsoft SQL Server.You must make several important design decisions when creating a user-defined type (UDT) to be installed 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. Per poter essere registrata con SQL Server, la definizione del tipo definito dall'utente deve essere conforme alle specifiche per la creazione di tipi definiti dall'utente.
Requisiti per l'implementazione di tipi definiti dall'utente
Per l'esecuzione in SQL Server, il tipo definito dall'utente deve implementare i requisiti seguenti nella definizione del tipo definito dall'utente:
Il tipo definito dall'utente deve specificare Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute. L'uso di System.SerializableAttribute è facoltativo, ma consigliato.
Il tipo definito dall'utente 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 è compatibile con i valori 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.
Il tipo definito dall'utente 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 di stringa dell'oggetto.
Un tipo definito dall'utente con un formato di serializzazione definito dall'utente deve implementare l'interfaccia System.Data.IBinarySerialize e fornire un metodo Read e Write.
Il tipo definito dall'utente deve implementare System.Xml.Serialization.IXmlSerializable oppure tutti i campi e le proprietà pubblici devono essere di tipi xml serializzabili o decorati con l'attributo XmlIgnore se è necessario eseguire 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 dei 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 contenere più di 128 caratteri e devono essere conformi alle regole di denominazione di SQL Server per gli identificatori definiti in Identificatori di database.
sql_variant colonne non possono contenere istanze di un tipo definito dall'utente.
I membri ereditati non sono accessibili da Transact-SQL perché il sistema dei tipi di SQL Server non riconosce la gerarchia di ereditarietà tra tipi definiti dall'utente. È 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 di sola lettura. I membri statici non possono essere modificati.
Se il campo SqlUserDefinedTypeAttribute.MaxByteSize è impostato su -1, il tipo definito dall'utente serializzato può essere grande quanto il limite di dimensioni loB (Large Object) (attualmente 2 GB). Le dimensioni del tipo definito dall'utente 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 a SQL Server di archiviare una rappresentazione nativa efficiente del tipo definito dall'utente su disco. Il formato nativo è consigliato se il tipo definito dall'utente è 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 valore composti da campi dei tipi precedenti sono candidati validi per il formato nativo , ad esempio gli struct in Visual C#, o strutture come sono noti in Visual Basic. Ad esempio, un tipo definito dall'utente specificato con il formato di serializzazione nativa può contenere un campo di un altro tipo definito dall'utente specificato anche con il formato Nativo . Se la definizione del tipo definito dall'utente è più complessa e contiene tipi di dati non inclusi 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.
System.Runtime.InteropServices.StructLayoutAttribute deve essere specificato come StructLayout.LayoutKindSequential se il tipo definito dall'utente è 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 dei campi per i tipi definiti dall'utente con più valori.
Per un esempio di tipo definito dall'utente definito con la serializzazione nativa, vedere Point UDT in Coding User-Defined Types (Tipi definiti dall'utente).
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à Dell'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 i metodi Read and Write per il tipo definito dall'utente implementando l'interfaccia System.Data.Sql.IBinarySerialize .
Per un esempio di tipo definito dall'utente definito con la serializzazione UserDefined, vedere Currency UDT in Coding User-Defined Types .For an example of a UDT defined with UserDefined serialization, see the Currency UDT in Coding User-Defined Types.For an example of a UDT defined with UserDefined serialization, see the Currency UDT in Coding User-Defined Types.
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 del tipo definito dall'utente. L'attributo Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute indica che la classe è un tipo definito dall'utente e specifica lo spazio di archiviazione per il tipo definito dall'utente. Facoltativamente, è possibile specificare l'attributo Serializable , anche se SQL Server non richiede questa operazione.
Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute ha le proprietà seguenti.
Formato
Specifica il formato di serializzazione, che può essere Nativo o UserDefined, a seconda dei tipi di dati del tipo definito dall'utente.
IsByteOrdered
Valore booleano che determina il modo in cui SQL Server esegue confronti binari nel tipo definito dall'utente.
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 tipo definito dall'utente con serializzazione definita dall'utente specificato, MaxByteSize fa riferimento alle dimensioni totali del tipo definito dall'utente 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 il tipo definito dall'utente è maggiore di 8000 byte (le dimensioni totali non possono superare le dimensioni lob massime). Si consideri un tipo definito dall'utente 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 del tipo definito dall'utente serializzato: le dimensioni dei dati serializzati in formato binario più l'overhead generato dalla 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 un'operazione di confronto viene eseguita in SQL Server nei byte serializzati, i risultati devono essere uguali a se la stessa operazione di confronto fosse 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 i formati di serializzazione Native e UserDefined supportano gli operatori di confronto seguenti quando IsByteOrdered è impostato su true:
Uguale a (=)
Diverso da (!=)
Maggiore di (>)
Meno 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 i valori 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 i valori Nullbility in un tipo definito dall'utente, vedere Codifica di tipi definiti dall'utente.
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 definiti dall'utente.
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. Lo spazio dei nomi System.Xml.Serialization contiene classi utilizzate per serializzare 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 e la deserializzazione XML.
Oltre a eseguire conversioni esplicite da UDT a xml, la serializzazione XML consente di:
Usare Xquery sui valori delle istanze definite 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 di tipi definiti dall'utente, convertire in modo esplicito ogni colonna definita dall'utente nel tipo di dati xml nell'istruzione SELECT. È anche possibile convertire in modo esplicito le colonne in varbinary, varchar o nvarchar.