程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> SQL Server 2005中自定義類型(UDT)格式化時間

SQL Server 2005中自定義類型(UDT)格式化時間

編輯:關於SqlServer

 1.實現“用戶定義的類型”UDT的要求:

  • UDT 必須通過創建公共的 static(Microsoft Visual Basic 中為 Shared)Null 方法,在類或結構中實現 System.Data.SqlTypes.INullable 接口。默認情況下,SQL Server 是可識別 Null 的。這是為使在 UDT 中執行的代碼能夠識別 Null 值所必需的。

    這個對應的就是上面的代碼 public struct TypeTest:INullable。需要實現Null性,對null性的處理,是在這裡處理的。

     

    1   public static TypeTest Null
    2     {
    3         get
    4         {
    5             TypeTest h = new TypeTest();
    6             h.m_Null = true;
    7             return h;
    8         }
    9     }

      必須創建一個名為 IsNull 的屬性,在從 CLR 代碼中確定值是否為空值時,需要使用該屬性。SQL Server 發現 UDT 的空值實例時,將使用正常的空值處理方法保持該實例。服務器不會將時間浪費在序列化或反序列化 UDT 上(如果不是必須),也不會將空間浪費在存儲空值 UDT 上。這種空值檢查在每次從 CLR 引入 UDT 時執行,這意味著始終可以使用 Transact-SQL IS NULL 結構檢查空值 UDT。服務器也使用 IsNull 屬性來測試實例是否為空值。服務器確定 UDT 為空值後,可以使用其本機空值處理方法。

     

  • UDT 必須包含支持從其進行分析的公共 static (或 SharedParse 方法以及用於轉換到對象的字符串表示形式的 ToString 方法。

    該方法的處理,是在這段代碼中進行處理的:

    1   public override string ToString()
    2     {
    3         // 用您的代碼替換下列代碼
    4         return "";
    5     }

     

    具有用戶定義序列化格式的 UDT 必須實現 System.Data.IBinarySerialize 接口並提供 ReadWrite 方法。

    對Read和Write方法的實現是在實現接口IBinarySerialize時需要處理的。處理方法如下:

     

    代碼  1 
     2     public string result;
     3 
     4     public void Read(System.IO.BinaryReader r) 
     5     {
     6 
     7         this.result = r.ReadString();
     8     }
     9 
    10     public void Write(System.IO.BinaryWriter w) 
    11     {
    12 
    13         w.Write(this.result);
    14     }

     

    這段代碼需要自己手動的寫上去,實現Read和Write方法。

    下面是編寫用戶自定義類型的其他要求:

  • 該 UDT 必須實現 System.Xml.Serialization.IXMLSerializable,或者所有公共字段和屬性必須均屬於 XML 可序列化類型或者使用 XMLIgnore 屬性進行修飾(如果要求替代標准序列化)。
     
  • 一個 UDT 對象必須只存在一個序列化。如果序列化或反序列化例程識別了某一特定對象的多個表示形式,則驗證將失敗。
     
  • 為了確保服務器將字節順序的比較用於 UDT 值,SqlUserDefinedTypeAttribute.IsByteOrdered 必須為 true
     
  • 在類中定義的 UDT 必須具有不采用任何參數的公共構造函數。您可以選擇創建其他重載類構造函數。
     
  • 該 UDT 必須將數據元素作為公共字段或屬性過程公開。
     
  • 公共名稱不能長於 128 個字符,並且必須符合在標識符中定義的針對標識符的 SQL Server 命名規則。
     
  • sql_variant 列不能包含 UDT 的實例。
     
  • 繼承的成員無法從 Transact-SQL 訪問,因為 SQL Server 類型系統不知道 UDT 中的繼承層次結構。但是,您可以在創建類的結構時使用繼承,並且可以在該類型的托管代碼實現方式中調用此類方法。
     
  • 成員不能被重載,但類構造函數除外。如果您創建某一重載方法,則在 SQL Server 中注冊程序集或創建類型時將不會引發錯誤。在運行時將檢測到重載的方法,而不是在創建類型時檢測到。只要永不調用重載的方法,重載的方法就可以存在於類中。一旦您調用重載的方法,就會引發錯誤。
     
  • 任何 static(或 Shared)成員都必須聲明為常量或聲明為只讀。靜態成員將無法改變。
     
  • 從 SQL Server 2008 開始,如果 SqlUserDefinedTypeAttribute.MaxByteSize 字段設置為 -1,則序列化 UDT 在大小上可達到大對象 (LOB) 大小限制(目前為 2 GB)。該 UDT 的大小不能超過在 MaxByteSized 字段中指定的值。

    編寫用戶類型的本地序列化:

      為 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 格式,例如 C# 中的 structs(或者 Visual Basic 中已知的 Structures)。例如,用 Native 序列化格式指定的 UDT 可以包含也用 Native 格式指定的其他 UDT 的字段。如果 UDT 定義更復雜並且所包含的數據類型不在上述列表中,您必須改為指定 UserDefined 序列化格式。

    Native 格式具有以下要求:

    • 該類型不得指定 MaxByteSize 的值。

    • 所有字段必須都是可序列化的。

    • 如果 UDT 是在類中定義的並且不是結構,則必須將 StructLayoutAttribute 指定為 StructLayout.LayoutKindSequential。此屬性控制數據字段的實際布局並用於強制成員按它們出現的順序排列。SQL Server 使用此屬性確定具有多個值的 UDT 的字段順序。

    用戶自定義序列化,在我們自己編寫“用戶自定義類型”時,需要使用UserDefined,即需要將系統自動生成的代碼

    [Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native)]修改為:

    [Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined)]

    SqlUserDefinedTypeAttribute 屬性的 UserDefined 格式設置使開發人員能夠完全控制二進制格式。在將 Format 特性屬性指定為 UserDefined 時,您需要在代碼中采取以下操作:

    • 指定可選的 IsByteOrdered 特性屬性。默認值為 false。

    • 指定 SqlUserDefinedTypeAttribute 的 MaxByteSize 屬性。

    • 通過實現 IBinarySerialize 接口,編寫代碼以便為 UDT 實現 Read 和 Write 方法。

    好了,上面的內容是我們再進行編寫我們自己的“用戶自定義類型”前需要了解的,呵呵。我也是了解了這麼多,然後就開始試著寫自己的“用戶自定義類型”。例子比較簡單,就是把輸入的時間統一成一個時間格式。希望能達到理解“用戶自定義類型”的目的。代碼如下:

     

    代碼  1 using System;
     2 using System.Data;
     3 using System.Data.SqlClIEnt;
     4 using System.Data.SqlTypes;
     5 using Microsoft.SqlServer.Server;
     6 
     7 [Serializable]
     8 [Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined,MaxByteSize=4000)]
     9 public struct TypeTime : INullable,IBinarySerialize
    10 {
    11     #region//實現IBinarySerizlize的Read和Write方法
    12 
    13     public string result;
    14 
    15     public void Read(System.IO.BinaryReader r) 
    16     {
    17 
    18         this.result = r.ReadString();
    19     }
    20 
    21     public void Write(System.IO.BinaryWriter w) 
    22     {
    23 
    24         w.Write(this.result);
    25     }
    26 
    27     #endregion
    28 
    29     public override string ToString()
    30     {
    31         // 用您的代碼替換下列代碼
    32         return result;
    33     }
    34 
    35     public bool IsNull
    36     {
    37         get
    38         {
    39             // 在此處放置代碼
    40             return m_Null;
    41         }
    42     }
    43 
    44     public static TypeTime Null
    45     {
    46         get
    47         {
    48             TypeTime h = new TypeTime();
    49             h.m_Null = true;
    50             return h;
    51         }
    52     }
    53 
    54     public static TypeTime Parse(SqlString s)
    55     {
    56         if (s.IsNull)
    57             return Null;
    58         TypeTime u = new TypeTime();
    59         // 在此處放置代碼
    60         u.result = OneTime(s);
    61         return u;
    62     }
    63 
    64     /// <summary>
    65     /// 將輸入的時間格式統一
    66     /// </summary>
    67     /// <param name="str"></param>
    68     /// <returns></returns>
    69     public static string OneTime(SqlString str)
    70     {
    71         return Convert.ToDateTime(str.Value).ToShortDateString() + Convert.ToDateTime(str.Value).ToShortTimeString();
    72     }
    73    
    74 
    75     // 私有成員
    76     private bool m_Null;
    77 }
    78 
    79 
    80 

     

    其中系統自動生成的兩個方法

    代碼  1   // 這是占位符方法
     2     public string Method1()
     3     {
     4         //在此處插入方法代碼
     5         return "Hello";
     6     }
     7 
     8     // 這是占位符靜態方法
     9     public static SqlString Method2()
    10     {
    11         //在此處插入方法代碼
    12         return new SqlString("Hello");
    13     }

    Method1和Method2可以刪掉,替換成自己的方法。

    其中需要注意的問題有這麼幾個:

    1.[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined,MaxByteSize=4000)]
    public struct TypeTest : INullable,IBinarySerialize  需要同時實現INullable和IBinarySeralize兩個接口;

    2.實現IBinarySeralize的Read和Write兩個方法;

    3.SqlString是數據庫類型,使用的時候,需要使用它的.value屬性,轉換成數據類型string 才能使用。

    好了,這個問題被解決掉了。

    碰到問題的時候,要冷靜,知道自己想要什麼,剩下的就是想辦法去拿;自己不知道怎麼能拿到,呵呵,就看看誰拿到了,然後跟人家學就好了。話是這麼說的,我也是這麼告訴自己的,呵呵,有時候,我也會因為某個問題沒能解決頭大。慢慢來,告訴自己冷靜就好,問題的產生,就是用來解決的。開心,好運!

                             

                                  如有轉載請注明出處謝謝合作!!!

    簽名:做一番一生引以為豪的事業;找一個一生榮辱與共的妻子;在有生之年報答幫過我的人;並有能力幫助需要幫助的人;

    博客園主頁歡迎大家過來交流探討:http://sufei.cnblogs.com/           

    QQ:361983679 Email:[email protected]  MSN:[email protected] 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved