はじめてのSQL Server 2005その2
SQLCLRを使ってユーザ定義型を作成してみます。VS2005が作成するユーザ定義型のひな形では、
[Serializable] [Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native)] public struct UserDefinedType : INullable
このように、Format.Nativeが指定されています。この場合、ユーザ定義型のメンバーには値型しか含めることが出来ません。しかし、それだとstring型が使えないので結構つらいです。そこで、ユーザ定義型に参照型を含める方法を見てみようと思います。
using System; using System.Data; using System.Data.SqlClient; using System.Data.SqlTypes; using Microsoft.SqlServer.Server; /// <summary> /// 参照型を含むユーザ定義型なので、Format.UserDefinedにして、 /// IBinarySerializeを実装 /// </summary> [Serializable] [Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined, MaxByteSize=132)] public struct Person : INullable, IBinarySerialize { string firstname; string lastname; int age; public string FirstName { get { return firstname; } } public string LastName { get { return lastname; } } public int Age { get { return age; } } public override string ToString() { return String.Format("FirstName={0},LastName={1},Age={2}", firstname, lastname, age); } public bool IsNull { get { return m_Null; } } public static Person Null { get { Person h = new Person(); h.m_Null = true; return h; } } /// <summary> /// 文字列表現「名前,名字,年齢」からオブジェクトを生成 /// </summary> /// <param name="s"></param> /// <returns></returns> public static Person Parse(SqlString s) { if (s.IsNull) return Null; Person u = new Person(); string[] ss = s.Value.Split(','); u.firstname = ss[0]; u.lastname = ss[1]; u.age = Int32.Parse(ss[2]); return u; } private bool m_Null; #region IBinarySerialize メンバ public void Read(System.IO.BinaryReader r) { m_Null = r.ReadBoolean(); if (!m_Null) { // Nullでないので、メンバーを読み込む firstname = r.ReadString(); lastname = r.ReadString(); age = r.ReadInt32(); } } public void Write(System.IO.BinaryWriter w) { w.Write(m_Null); if (!m_Null) { // Nullでないので、メンバーを書き出す w.Write(firstname); w.Write(lastname); w.Write(age); } } #endregion }
まず、Format.NativeからFormat.UserDefinedに変更し、使用する最大バイト数を指定します。ここで指定している132は適当なのであまり気にしないでください。(^^; また、IBinarySerializeを実装して、シリアライズ可能にする必要があります。
さて、ユーザ定義型が出来たので、これを使ってテーブルを作成してみましょう。
CREATE TABLE [dbo].[Persons]( [parson] [dbo].[Person] NULL ) ON [PRIMARY]
ツールで自動生成したスクリプトなので分かり難いですが、テーブルPersonsにはフィールドpersonがあり、その型はユーザ定義型のPersonが指定されています。では、このテーブルに対してクエリーを発行してみましょう。
using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Data.SqlClient; partial class Program { static void Main(string[] args) { SqlConnection conn = new SqlConnection(connectionString); try { conn.Open(); SqlCommand cmd = new SqlCommand("select * from Persons", conn); SqlDataReader r = cmd.ExecuteReader(); while (r.Read()) { Person p = (Person)r.GetValue(0); Console.WriteLine("{0} {1} ({2})", p.LastName, p.FirstName, p.Age); } r.Close(); } finally { if (conn != null) conn.Dispose(); } } }
クエリーの結果をPersonオブジェクトとして受け取ることが出来ますね。