Condividi tramite


Requisiti del tipo definito dall'utente

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 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 dei 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 il Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute. L'uso del 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 static pubblico (Shared in Visual Basic) Null metodo. 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 static pubblico (o Shared) Parse metodo che supporta l'analisi da e un metodo pubblico di ToString 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 Read e un metodo Write.

  • Il tipo definito dall'utente deve implementare System.Xml.Serialization.IXmlSerializableoppure tutti i campi e le proprietà pubblici devono essere di tipi 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 di byte hanno esito negativo.

  • Un tipo definito dall'utente specificato in una classe deve disporre di un costruttore pubblico che non accetta argomenti. Facoltativamente, è possibile creare più costruttori di classi di overload.

  • 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 è a conoscenza della 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. I metodi di overload possono esistere nella classe purché non vengano mai richiamati. Quando si richiama il metodo di overload, viene generato un errore.

  • Qualsiasi membro static (o Shared) deve essere dichiarato come costanti o di sola lettura. I membri statici non possono essere modificabili.

  • 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. Questa operazione viene usata sul lato client in situazioni in cui è consigliabile confrontare o ordinare con precisione i valori definiti dall'utente.

Serializzazione nativa

La scelta degli attributi di serializzazione corretti per il tipo definito dall'utente dipende dal tipo di tipo definito dall'utente che si sta tentando di creare. Il formato di serializzazione Native usa una struttura semplice che consente a SQL Server di archiviare una rappresentazione nativa efficiente del tipo definito dall'utente su disco. Il formato Native è consigliato se il tipo definito dall'utente è semplice e contiene solo campi dei tipi seguenti:

bool, byte, sbyte , breve, ushort, int, uint, long , ulong, float, double, , , , , , , , ,

I tipi valore composti da campi di questi tipi sono candidati validi per Native formato, ad esempio struct in C#, o Structure come sono noti in Visual Basic .NET. Ad esempio, un tipo definito dall'utente specificato con il formato di serializzazione Native potrebbe contenere un campo di un altro tipo definito dall'utente specificato anche con il formato Native. Se la definizione del tipo definito dall'utente è più complessa e contiene tipi di dati non presenti nell'elenco precedente, è necessario specificare invece il formato di serializzazione UserDefined.

Il formato Native presenta i requisiti seguenti:

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

  • Tutti i campi devono essere serializzabili.

  • Il 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 con Native serializzazione, vedere Point tipo definito dall'utente in Creare tipi definiti dall'utente con ADO.NET.

Serializzazione Definita dall'utente

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 azioni seguenti nel codice:

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

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

  • Scrivere codice per implementare metodi Read e Write per il tipo definito dall'utente implementando l'interfaccia System.Data.Sql.IBinarySerialize.

Per un esempio di tipo definito dall'utente definito con UserDefined serializzazione, vedere Currency UDT in Creare tipi definiti dall'utente con ADO.NET.

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 il 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 la risorsa di archiviazione per il tipo definito dall'utente. Facoltativamente, è possibile specificare l'attributo Serializable, anche se SQL Server non richiede questa operazione.

Il Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute ha le proprietà seguenti.

Formato

Specifica il formato di serializzazione, che può essere Native o UserDefined, a seconda dei tipi di dati del tipo definito dall'utente.

IsByteOrdered

Valore Boolean 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 di 1 da 8000o impostato su -1 per indicare che il tipo definito dall'utente è maggiore di 8.000 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.

Set 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 è 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.

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

  • Possibilità di usare Transact-SQL ORDER BYclausole , GROUP BYe 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.

Sia i formati di serializzazione Native che di 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 (<=)

Implementare il 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 Creare tipi definiti dall'utente con ADO.NET.

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 la conversione di una stringa in un tipo definito dall'utente. Deve essere dichiarato come static (o Shared 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 Creare tipi definiti dall'utente con ADO.NET.

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 gli oggetti in documenti o flussi in formato XML. È possibile scegliere di implementare xml serializzazione 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 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 dei 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.