使用者定義型別需求

建立要安裝在 Microsoft SQL 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) 成員都必須宣告為常數或唯讀。靜態成員無法時常變動。

  • 如果 SqlUserDefinedTypeAttribute.MaxByteSize 欄位設定為 -1,則序列化的 UDT 可以與大型物件 (LOB) 的大小限制 (目前為 2 GB) 一樣大。UDT 的大小不得超過 MaxByteSized 欄位中指定的值。

[!附註]

儘管伺服器不會使用它來執行比較,但您可以選擇性地實作能夠公開單一方法 CompareTo 的 System.IComparable 介面。在需要對 UDT 值進行精確比較或排序的情況下,將會在用戶端上使用它。

原生序列化

若要為 UDT 選擇正確的序列化屬性,必須視您嘗試建立的 UDT 型別而定。 Native 序列化格式使用很簡單的結構,其可以讓 SQL Server 將有效率的 UDT 原生表示法儲存在磁碟上。如果 UDT 是簡單的,並且僅包含下列型別的欄位,則建議使用 Native 格式:

boolbytesbyteshortushortintuintlongulongfloatdoubleSqlByteSqlInt16SqlInt32SqlInt64SqlDateTimeSqlSingleSqlDoubleSqlMoneySqlBoolean

組成上述類型之欄位的值類型是 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。

請參閱

其他資源