UDT 上的每个操作(除了比较)都要求 UDT 的值反序列化,接着进行方法调用。这种模式有与之相关的固定开销。如果要将类型建模为 UDT(相对于表中的列),则在访问类型属性(相对于表中的列)时应该考虑这种差别。如果类型上的行为非常复杂,则应该考虑使用 UDT。如果类型没有任何与之相关的行为,则应该考虑将数据存储为表中的列。
如果发现需要实现相关函数的库,则 UDT 中的静态方法是一种可以方便地创建这种库的封装机制。可以通过使用 :: 语法来调用T-SQL 中的静态方法,如下所示:
select imagetype::MyFunction(@arg1)
实际方案
客户希望在 UmAlQuraCalendar 中存储日期时间值,这与 SQL Server 日期时间数据类型使用的 Gregorian 日历不同。他们想让这个日期类型具有相同的基本行为集,即字符串转换、日期部分、日期算法和 GetDate()。
下面是这一数据类型的代码片段。它使用 UmAlQuraCalendar 2.0 版,这是 .NET Framework 中的新类型。
[SqlUserDefinedType(Format.Native, IsByteOrdered = true)] public struct UmAlQuraDateTime : INullable { //Private state private long dtTicks; //Calendar object used for all calendar-specific operations private static readonly UmAlQuraCalendar s_calendar = new UmAlQuraCalendar(); public static UmAlQuraDateTime Null { get { UmAlQuraDateTime dt = new UmAlQuraDateTime(); dt.isNull = true; return dt; } } public bool IsNull { get { return this.isNull; } } //Convert into CLR DateTime type public DateTime DateTime { get { return new DateTime(this.dtTicks); } }
字符串转换和创建新值:
public static UmAlQuraDateTime Parse(SqlString s) ... public override string ToString() ... public static UmAlQuraDateTime ParseUsingFormat(string data, string fmt) ... public string ToStringUsingFormat(string format) ... public static UmAlQuraDateTime Now { get { return new UmAlQuraDateTime(DateTime.Now); } } public static UmAlQuraDateTime FromSqlDateTime(SqlDateTime d) { if (d.IsNull) return Null; return new UmAlQuraDateTime(d.Value); }
日期部分类似功能:
public int Year { get { return s_calendar.GetYear(this.DateTime); } } public int Month ... public int Hour ... public int Minute ... public int Second ... public double Milliseconds ... public long Ticks ... public SqlDateTime ToSqlDateTime() { return new SqlDateTime(this.DateTime); }
DateAdd/DateDiff:
public UmAlQuraDateTime AddYears(int years) { return new UmAlQuraDateTime(s_calendar.AddYears(this.DateTime, years)); } public UmAlQuraDateTime AddDays(int days) ... public UmAlQuraDateTime AddMonths(int months) ... public UmAlQuraDateTime AddHours(int hours) ... public UmAlQuraDateTime AddMinutes(int minutes) ... public double DiffDays(UmAlQuraDateTime other) ...
下面是一些处理 T-SQL 中的类型的示例操作:
-- convert it to arabic (for testing purposes) declare @h hijridatetime set @h = hijridatetime::ParseArabicString('01/02/1400') select @h.ToArabicString(), @h.ToArabicStringUsingFormat('F') -- convert sql datetime to hijri and back declare @h hijridatetime set @h = hijridatetime::FromSqlDateTime(GetDate()) select @h.ToArabicString(), @h.ToSqlDateTime() -- get the current hijri datetime, in two ways select hijridatetime::Now.ToString(), hijridatetime::FromSqlDateTime(GetDate()).ToString() -- do some arithmetic: declare @h hijridatetime, @d datetime set @h = hijridatetime::Now -- get the current hijri datetime set @h = @h.AddDays(10) -- add ten days to it set @d = GetDate() -- current sql date set @d = DateAdd(day, 10, @d) -- add ten days to the sql datetime -- print 'em both, should be the same select @h.ToSqlDateTime(), @d -- datepart declare @h hijridatetime set @h = hijridatetime::Now -- get the current hijri datetime select @h.Year as year, @h.Month as month, @h.Day as month
小结
本文介绍了使用 SQL Server 2005 中的 CLR 集成功能的指导原则、具体使用情况和示例。数据库应用程序开发人员和架构师应该结合集中讨论 SQL Server 2005 中的其他功能区(如 TransacT-SQL、XML 和 Service Broker)的指导原则的其他文章来阅读本文。
将来,我们计划在这一领域提供更多白皮书,讲解 CLR 集成的可管理性、监控和故障排除方面的指导原则。






