使用者定義型別需求
建立要安裝在 MicrosoftSQL Server 中的使用者定義型別 (UDT) 時,您必須做數個重要的設計決定。對於大部分的 UDT 而言,雖然將 UDT 當做類別來建立也是一種選擇,但是建議將 UDT 當做結構來建立。UDT 定義必須符合建立 UDT 的規格,才能讓它使用 SQL Server 註冊。
實作 UDT 的需求
若要在 SQL Server 中執行,UDT 必須實作 UDT 定義中的下列需求:
UDT 必須指定 Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute。雖然 System.SerializableAttribute 是選擇性使用的,但仍建議使用。
UDT 必須藉由建立公用 static (Microsoft Visual Basic 中為 Shared) Null 方法,在類別或結構中實作 System.Data.SqlTypes.INullable 介面。依預設,SQL Server 能夠辨識 Null。若要讓在 UDT 中執行的程式碼能夠辨識 Null 值,此為必要選項。
UDT 必須包含可支援從物件字串表示法進行剖析的公用 static (或 Shared) Parse 方法,以及轉換為物件字串表示法的公用 ToString 方法。
含有使用者定義序列化格式的 UDT 必須實作 System.Data.IBinarySerialize 介面,並提供 Read 和 Write 方法。
UDT 必須實作 System.Xml.Serialization.IXmlSerializable,或如果必須覆寫標準序列化,所有的公用欄位和屬性都必須屬於可 XML 序列化或可使用 XmlIgnore 屬性來修飾的類型。
一個 UDT 物件必須僅有一個序列化。如果序列化或還原序列化常式識別一個以上的特定物件表示法,則驗證會失敗。
SqlUserDefinedTypeAttribute.IsByteOrdered 必須是 true,才能按照位元組順序比較資料。如果沒有實作 IComparable 介面,而且 SqlUserDefinedTypeAttribute.IsByteOrdered 是 false,位元組順序比較將會失敗。
以類別定義的 UDT 必須具有不使用引數的公用建構函式。您可以選擇性地建立其他多載類別建構函式。
UDT 必須將資料元素公開為公用欄位或屬性程序。
公用名稱長度不得超過 128 個字元,而且必須符合識別碼在<識別碼>中定義的 SQL Server 命名規則。
sql_variant 資料行無法包含 UDT 的執行個體。
因為 SQL Server 類型系統不會從 UDT 辨識繼承階層,所以無法從 Transact-SQL 存取繼承成員。不過,結構化類別時可以使用繼承,並可以在型別的 Managed 程式碼實作中呼叫此類方法。
成員不可多載,但類別建構函式除外。如果您有建立多載方法,則當您註冊組件或是在 SQL Server 中建立類型時,就不會引發錯誤。多載方法的偵測會於執行階段發生,而不是在建立類型時發生。在叫用之前,多載方法會一直存在於類別中。一旦叫用多載方法,將會引發錯誤。
任何 static (或 Shared) 成員都必須宣告為常數或唯讀。靜態成員無法時常變動。
從 SQL Server 2008 開始,如果 SqlUserDefinedTypeAttribute.MaxByteSize 欄位設定為 -1,序列化的 UDT 可以與大型物件 (LOB) 大小限制 (目前是 2 GB) 一樣大。UDT 的大小不得超過 MaxByteSized 欄位中指定的值。
[!附註]
儘管伺服器不會使用它來執行比較,但您可以選擇性地實作能夠公開單一方法 CompareTo 的 System.IComparable 介面。在需要對 UDT 值進行精確比較或排序的情況下,將會在用戶端上使用它。
原生序列化
若要為 UDT 選擇正確的序列化屬性,必須視您嘗試建立的 UDT 型別而定。 Native 序列化格式使用很簡單的結構,其可以讓 SQL Server 將有效率的 UDT 原生表示法儲存在磁碟上。如果 UDT 是簡單的,並且僅包含下列型別的欄位,則建議使用 Native 格式:
bool、byte、sbyte、short、ushort、int、uint、long、ulong、float、double、SqlByte、SqlInt16、SqlInt32、SqlInt64、SqlDateTime、SqlSingle、SqlDouble、SqlMoney、SqlBoolean
組成上述類型之欄位的值類型是 Native 格式很好的候選項目,如 Visual C# 中的 structs (或 Visual Basic 中的 Structures)。例如,使用 Native 序列化格式指定的 UDT 可能包含也使用 Native 格式指定之其他 UDT 的欄位。如果 UDT 定義較為複雜,且包含不在上面清單中的資料型別,則必須改為指定 UserDefined 序列化格式。
Native 格式具有下列需求:
型別不可指定 Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.MaxByteSize 的值。
所有欄位都必須為可序列化。
如果 UDT 是以類別而非以結構來定義,System.Runtime.InteropServices.StructLayoutAttribute 就必須指定為 StructLayout.LayoutKindSequential。此屬性可以控制資料欄位的實體配置,並用於強制以成員出現的順序對成員進行配置。SQL Server 會使用此屬性來判定具有多個值之 UDT 的欄位順序。
如需使用 Native 序列化定義之 UDT 的範例,請參閱 撰寫使用者定義型別的程式碼 中的<Point UDT>。
UserDefined 序列化
Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute 屬性的 UserDefined 格式設定可讓開發人員完全控制二進位格式。將 Format 屬性指定為 UserDefined 時,您必須在程式碼中進行下列動作:
指定選擇性的 IsByteOrdered 屬性。預設值為 false。
指定 Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute 的 MaxByteSize 屬性。
藉由實作 System.Data.Sql.IBinarySerialize 介面,撰寫程式碼以實作 UDT 的 Read 及 Write 方法。
如需使用 UserDefined 序列化定義之 UDT 的範例,請參閱<撰寫使用者定義型別的程式碼>中的「Currency UDT」。
[!附註]
從 SQL Server 2005 RTM 版開始,允許包含使用者定義序列化的 CLR UDT 建立其欄位的索引,做為非保存之計算資料行或檢視的一部分。在此類情況下,不具決定性的 UDT 序列化/還原序列化可能會導致索引損毀,因此已經從 SQL Server 2005 SP1 移除。在 SQL Server 2005 SP1 中,UDT 欄位必須使用原生序列化,或保存下來進行索引。UDT 欄位上任何現有的索引應該都會跟往常一樣,繼續運作。
序列化屬性
屬性會決定如何使用序列化來建構 UDT 的儲存表示法,並將 UDT 以傳值方式傳輸到用戶端。建立 UDT 時,您必須指定 Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute。Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute 屬性表示類別為 UDT,並指定該 UDT 的儲存。您可以選擇性地指定 Serializable 屬性,但是在 SQL Server 中不需要執行這項動作。
Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute 具有下列屬性。
Format
指定序列化格式,其可以為 Native 或 UserDefined,這必須視 UDT 的資料類型而定。IsByteOrdered
決定 SQL Server 如何在 UDT 上執行二進位比較的 Boolean 值。IsFixedLength
表示此 UDT 的所有執行個體是否為相同長度。MaxByteSize
執行個體的大小最大值 (位元組)。您必須使用 UserDefined 序列化格式指定 MaxByteSize。如果 UDT 已指定使用者定義的序列化,對此 UDT 而言,MaxByteSize 是指 UDT 在其序列化形式 (由使用者所定義) 的總大小。MaxByteSize 的值必須在 1 到 8000 的範圍內,或設定為 -1,表示 UDT 大於 8000 個位元組 (總大小不得超過 LOB 大小的上限)。以一個具有 10 個字元字串之屬性的 UDT (System.Char) 為例。當 UDT 使用 BinaryWriter 序列化時,序列化字串的總大小是 UDT 個位元組:每個 Unicode 2-16 字元兩個位元組,乘以字元的最大數目,再加上序列化二進位資料流所造成的兩個控制位元組負擔。因此,在決定 MaxByteSize 的值時,必須考慮序列化 UDT 的總大小:以二進位形式序列化資料的大小,加上序列化所耗用的位元組。ValidationMethodName
用於驗證 UDT 執行個體之方法的名稱。
設定 IsByteOrdered
將 Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.IsByteOrdered 屬性設為 true 時,您即已保證序列化的二進位資料可以用於資訊的語意排序。因此,每個位元組排序的 UDT 物件執行個體只能有一個序列化表示法。當在 SQL Server 中對已序列化的位元組執行比較作業時,其結果應與在 Managed 程式碼中執行比較作業的結果相同。將 IsByteOrdered 設為 true 時,還可支援下列功能:
在此型別之資料行上建立索引的功能。
在此類型的資料行上建立主索引鍵及外部索引鍵,以及建立 CHECK 條件約束及 UNIQUE 條件約束的功能。
使用 Transact-SQL ORDER BY、GROUP BY 及 PARTITION BY 子句的功能。在這些情況下,類型的二進位表示法用於決定順序。
在 Transact-SQL 陳述式中使用比較運算子的功能。
保留此類型之計算資料行的功能。
請注意,當 IsByteOrdered 設定為 true 時,Native 及 UserDefined 序列化格式可以支援下列比較運算子:
等於 (=)
不等於 (!=)
大於 (>)
小於 (<)
大於或等於 (>=)
小於或等於 (<=)
實作 Null 屬性
除了必須正確地指定組件的屬性外,您的類別還必須能夠支援 Null 屬性。載入 SQL Server 的 UDT 可辨識 Null,但是為了讓 UDT 能夠辨識 Null 值,此類別必須實作 INullable 介面。如需如何在 UDT 中實作 Null 屬性的詳細資訊及範例,請參閱 撰寫使用者定義型別的程式碼。
字串轉換
若要支援字串與 UDT 的來回轉換,則必須在您的類別中提供 Parse 方法及 ToString 方法。Parse 方法允許將字串轉換成 UDT。它必須宣告為 static (或 Visual Basic 中的 Shared),並採用型別 System.Data.SqlTypes.SqlString 的參數。如需如何實作 Parse 及 ToString 方法的詳細資訊及範例,請參閱 撰寫使用者定義型別的程式碼。
XML 序列化
UDT 必須藉由符合 XML 序列化合約,來支援 xml 資料類型間的轉換。System.Xml.Serialization 命名空間包含用於將物件序列化為 XML 格式文件或資料流的類別。您可以選擇使用 IXmlSerializable 介面 (該介面可提供 XML 序列化和還原序列化的自訂格式),以便實作 xml 序列化。
除了能夠執行 UDT 到 xml 的明確轉換外,XML 序列化還可讓您:
轉換至 xml 資料類型後,在 UDT 執行個體的值上使用 Xquery。
搭配 SQL Server 中的原生 XML Web 服務使用參數化查詢和 Web 方法中的 UDT。如需詳細資訊,請參閱<處理 xml 資料類型及 CLR 使用者自訂類型>。
使用 UDT 接收 XML 資料的大量載入。
序列化包含具有 UDT 資料行之資料表的 DataSet。
在 FOR XML 查詢中不會序列化 UDT。若要執行顯示 UDT 之 XML 序列化的 FOR XML 查詢,請在 SELECT 陳述式中將每個 UDT 資料行明確轉換為 xml 資料類型。您還可以將資料行明確轉換為 varbinary、varchar 或 nvarchar。