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

SQL Server 2005中自定義類型(UDT)年齡段

編輯:關於SqlServer

學習 SQL Server CLR 沒有多久,就遇到了一個讓我很郁悶的問題;如何處理當“用戶定義類型”中因出現像 string 這樣的引用類型而引發地一些問題?

下面是我經過查詢相關資料而得出的解決方法(代碼所示):
 

用戶定義類型   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=10)]
  9 public struct AgeGroup : INullable, IBinarySerialize
 10 {
 11     public override string ToString()
 12     {
 13         return ageGroup;
 14     }
 15 
 16     #region 自動生成
 17 
 18     public bool IsNull
 19     {
 20         get
 21         {
 22             return m_Null;
 23         }
 24     }
 25 
 26     public static AgeGroup Null
 27     {
 28         get
 29         {
 30             AgeGroup h = new AgeGroup();
 31             h.m_Null = true;
 32             return h;
 33         }
 34     }
 35 
 36     #endregion
 37 
 38     public static AgeGroup Parse(SqlString s)
 39     {
 40         if (s.IsNull)
 41             return Null;
 42         AgeGroup u = new AgeGroup();
 43         u.ageGroup = AgeGroup.ComputeAgeGroup(s.Value);
 44         return u;
 45     }
 46 
 47     /// <summary>
 48     /// 計算年齡段
 49     /// </summary>
 50     /// <param name="s">用戶輸入字串</param>
 51     /// <returns></returns>
 52     public static string ComputeAgeGroup(string s)
 53     {
 54         int tempInt = -1;
 55 
 56         if (int.TryParse(s, out tempInt))
 57         {
 58             if (tempInt >= 0)
 59             {
 60                 if (tempInt <= 6)
 61                 {
 62                     return "童年";
 63                 }
 64                 else if (tempInt > 6 && tempInt <= 17)
 65                 {
 66                     return "少年";
 67                 }
 68                 else if (tempInt > 17 && tempInt <= 40)
 69                 {
 70                     return "青年";
 71                 }
 72                 else if (tempInt > 40 && tempInt <= 65)
 73                 {
 74                     return "中年";
 75                 }
 76                 else
 77                 {
 78                     return "老年";
 79                 }
 80             }
 81             else
 82             {
 83                 return string.Empty;
 84             }
 85         }
 86         else
 87         {
 88             return string.Empty;
 89         }
 90     }
 91 
 92     // 年齡段名稱
 93     public string ageGroup;
 94     // 標示是否為空(自動生成)
 95     private bool m_Null;
 96 
 97     #region IBinarySerialize 成員
 98 
 99     public void Read(System.IO.BinaryReader r)
100     {
101         this.ageGroup = r.ReadString();
102     }
103 
104     public void Write(System.IO.BinaryWriter w)
105     {
106         w.Write(this.ageGroup);
107     }
108 
109     #endregion
110 }
111 
112 
113 


 

 因為“用戶定義類型”是以值類型對象的形式來實現的,所以當有像 string 這樣的引用類型的時候就會有
 

     對類型 "Demo_SQLSERVER.AgeGroup" 做標記以進行本機序列化,但是類型 "Demo_SQLSERVER.AgeGroup" 的字段
"ageGroup" 為 string 類型(它是非值類型)...
 

類似這樣的錯誤信息提示 。
 

     出現這個錯誤的原因是,對於int、double等類型的數據,它們直接對應操作系統使用的本機數據類型,例如int和double在C++中都有相應的 類型,實際上在C#和C++中它們的結構都是一樣的,因此在序列化的時候可以將這些類型的字段當作本機類型來處理。而對於類類型的字段,例如 string,在操作系統中沒有對應的數據類型,因此這些字段不能直接序列化。用戶必須手動添加序列化代碼,告訴SQL Server如何去序列化這些類型的字段。 

因此,需要實現 IBinarySerialize 接口以告訴 SQL Server 如何去實例化指定的字段。
然而問題又來了:
 

     對類型 "Demo_SQLSERVER.AgeGroup" 做標記以進行本機序列化,但是類型 "Demo_SQLSERVER.AgeGroup" 的字段 "ageGroup" 對於本機序列化無效。
 

我們還需要修改 VS 自動給我們生成的特性:
 

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

修改為:
 

[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined, MaxByteSize=10)]

在這裡,對於用戶自定義的格式序列化,指定 MaxByteSize 屬性(表示聚合實例的最大大小的 Int32 值)是必須的;另外,此屬性的最大允許值 (8000) 由 MaxByteSizeValue 字段指定。
  需要注意的是,對於指定了用戶定義的序列化的聚合,MaxByteSize 是指序列化的數據的總大小。以一個序列化包含 10 個字符 (Char) 的字符串的聚合為例。當使用 BinaryWriter  序列化該字符串時,序列化後的字符串的總大小為 22 個字節:每個 Unicode UTF-16 字符占據的字節數 2 乘以最大字符數 10,再加上序列化二進制流所引入的開銷占用的 2 個控制字節。因此,在確定 MaxByteSize 的值時,必須考慮序列化的數據的總大小:二進制形式的序列化數據的大小加上序列化引入的開銷。
 


 

  到這裡,就可以“生成”一下,“部署”到SQL Server 實例裡使用自己定義的類型了。
 


參考資料:
http://technet.microsoft.com/zh-cn/library/ms131069.ASPx
http://msdn.microsoft.com/zh-cn/library/microsoft.sqlserver.server.sqluserdefinedaggregateattribute.maxbytesize%28VS.80%29.ASPx
http://kb.cnblogs.com/a/1546876/
 


如有不妥之處,還望不吝賜教。

                         

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

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

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

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

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