<?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>.NET関連</title><link>http://blogs.wankuma.com/ganfield/category/1036.aspx</link><description>.NET関連</description><managingEditor>がんふぃーるど(ganfield@wankuma.com)</managingEditor><dc:language>ja-JP</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>アプリケーションコンテキスト その１ - Oracle</title><link>http://blogs.wankuma.com/ganfield/archive/2008/08/18/153314.aspx</link><pubDate>Mon, 18 Aug 2008 01:38:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2008/08/18/153314.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/153314.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2008/08/18/153314.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/153314.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/153314.aspx</trackback:ping><description>&lt;P&gt;Oracleにはアプリケーションコンテキストというものがあります。ASP.NETで言うところの「セッション」みたいなもので、基本はKey-Valueで構成される情報を保持しています。Oracleのマニュアルを見るとCREATE CONTEXT文というのがちゃんと用意されており、ユーザ定義のアプリケーションコンテキストを使用すればかなり柔軟なアプリケーションを作成することが可能です。&lt;/P&gt;
&lt;P&gt;今回は御触りということで、ユーザ定義のアプリケーションコンテキストは使用せずに組込みのアプリケーションコンテキスト「USERENV」を少しだけ使用します。&lt;/P&gt;
&lt;H4&gt;アプリケーションコンテキスト「USERENV」&lt;/H4&gt;
&lt;P&gt;USERENVにはセッションに関する情報がほぼ詰め込まれています。今回はこの中の「CLIENT_IDENTIFIER」を使用します。理由は至って簡単-ODP.NETのOracleConnection.ClientIdからお手軽に設定できるからです。&lt;/P&gt;
&lt;P&gt;その他の値については下記のOracleのドキュメントを参照してください。&lt;/P&gt;
&lt;P&gt;&lt;A title=http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/server.111/E05750-02/functions.htm#11790 href="http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/server.111/E05750-02/functions.htm#11790"&gt;http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/server.111/E05750-02/functions.htm#11790&lt;/A&gt;&lt;/P&gt;
&lt;H4&gt;アプリケーションコンテキストの確認方法&lt;/H4&gt;
&lt;P&gt;アプリケーションコンテキスト確認用の関数があるので、それを使用します。&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;SYS_CONTEXT(namespace, parameter [, length ])&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;namespaceにUSERENV&lt;/P&gt;
&lt;P&gt;parameterにCLIENT_IDENTIFIER&lt;/P&gt;
&lt;P&gt;を指定します。lengthはオプショナルな設定値なので今回は無視（デフォルト値は256）&lt;/P&gt;
&lt;P&gt;　※USERENV関数というのもありますが下位互換用です。またUSERENV関数にはCLIENT_IDENTIFIERを取得する機能は存在しないので、基本SYS_CONTEXTを使用します。&lt;/P&gt;
&lt;H4&gt;ODP.NETでCLIENT_IDENTIFIERの設定&lt;/H4&gt;
&lt;P&gt;先に言ってしまいましたが、ODP.NETの以下のプロパティを設定します。&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;OracleConnection.ClientId&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;このプロパティは接続をOpenした後にのみ設定可能です。ClientIdは接続中つねに有効になり、Closeと共に解放されます（nullが設定される）。&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=800 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=798&gt;
&lt;P&gt;using (OracleConnection conn = new OracleConnection("user id=XXXX; password=YYYY; data source=xe"))&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; conn.Open(); 
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; conn.ClientId = "30";&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; command = conn.CreateCommand();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; command.CommandText = "SELECT SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER') FROM DUAL";&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = command.ExecuteScalar();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(result.Equals(System.DBNull.Value) ? "null" : result.ToString());&lt;BR&gt;}&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;H4&gt;アプリケーションコンテキストを使用してVIEWへ値を動的に渡す&lt;/H4&gt;
&lt;P&gt;アプリケーションコンテキストは関数を通して取得できるということで、VIEWなどに対して動的に値を渡すことが可能です。VIEWであれば、使用しているSQL側でWHERE句に条件を設定することで同じことが当然できますが、セキュリティ的な要件をVIEWでコントロールしたい場合などに役立ちます。（Oracleではセキュリティに関して、仮想プライベートデータベースという便利な機能がありますが、今回はそれを使用しません。）&lt;/P&gt;
&lt;P&gt;ためしに以下のようなVIEWをOracleのHRスキーマ上に作成します。&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=800 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=800&gt;
&lt;P&gt;-- マネージャ直下の部下を参照できるVIEW&lt;BR&gt;CREATE OR REPLACE VIEW HR.EMPLOYEES_UNDER_MANAGER1&lt;BR&gt;AS&lt;BR&gt;SELECT * FROM HR.EMPLOYEES WHERE MANAGER_ID = SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER')&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;このVIEWはClientIdに社員IDが設定されていることを前提に作られています。ClientIdの値を変えることで返却される行が変更されます。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;次回はユーザ定義のアプリケーションコンテキストの作成方法について説明しようと思います。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/153314.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>NVelocity - テキストのテンプレートエンジン</title><link>http://blogs.wankuma.com/ganfield/archive/2008/07/10/148258.aspx</link><pubDate>Thu, 10 Jul 2008 01:57:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2008/07/10/148258.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/148258.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2008/07/10/148258.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/148258.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/148258.aspx</trackback:ping><description>&lt;p&gt;.NETで使用できるテキストテンプレートエンジンです。&lt;/p&gt; &lt;p&gt;最近やっている仕事の関係上、開発用ツールを作成したくなる場合が多く、ちょっとしたデータベースのDDL文などのテキストファイルを作成する場合が多く、もうちっと楽＆美しく（？）作りたいな～なんて思っているときに発見しました。&lt;/p&gt; &lt;p&gt;上手に使用すればメール本文を作成するテンプレートエンジンとしても利用可能にできそうです。&lt;/p&gt; &lt;p&gt;ちょっとおしゃれに（無駄にｗ）テキストファイルを作ってみたいときは使ってみて下さい。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="https://svn.castleproject.org/svn/castle/trunk/Tools/NVelocity/"&gt;NVelocity (SVNリポジトリ)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://codezine.jp/a/article/aid/373.aspx"&gt;CodeZine : テンプレートエンジンNVelocityを活用してテキストを生成する&lt;/a&gt;&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/148258.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>ユーザー定義集計関数&amp;hellip;とは微妙に違うCSV形式で文字列を集計 - LINQ</title><link>http://blogs.wankuma.com/ganfield/archive/2008/07/02/146658.aspx</link><pubDate>Wed, 02 Jul 2008 02:05:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2008/07/02/146658.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/146658.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2008/07/02/146658.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/146658.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/146658.aspx</trackback:ping><description>&lt;p&gt;&lt;a href="http://blogs.wankuma.com/ganfield/archive/2008/06/30/146270.aspx"&gt;前回&lt;/a&gt;はSQL Serverでその前がOracleだったので、ぢゃあ次はLINQってことで試してみました。&lt;/p&gt; &lt;p&gt;LINQの場合（というかC# 3.0の場合）は、Aggregateメソッドとラムダ式でうにゃうにゃっと書けば結構できてしまうので、細かいとこは省いてしまいます。&lt;/p&gt; &lt;h2&gt;基本&lt;/h2&gt; &lt;p&gt;基本は以下のラムダ式があればほぼ問題無いみたいです。（表現が間違っていたらごめんなさい＆指摘して下さい）&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2" width="700" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="700"&gt; &lt;p&gt;(TAccumulate, TSource) =&amp;gt; 処理&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;ということで、実際に集計処理をしてみましょう。&lt;/p&gt; &lt;h2&gt;集計処理&lt;/h2&gt; &lt;p&gt;サンプルでは適当な家族(family)の匿名型を利用して、性別ごとに家族の名前をカンマ区切りで集計します。&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2" width="700" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="700"&gt; &lt;p&gt;var family = new []{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new { Name = "父", Age = 40, Sex = "男" },&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new { Name = "母", Age = 40, Sex = "女" },&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new { Name = "娘", Age = 10, Sex = "女" },&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new { Name = "爺ちゃん", Age = 70, Sex = "男" },&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new { Name = "曾婆ちゃん", Age = 100, Sex = "女" },&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new { Name = "曾曾婆ちゃん", Age = 125, Sex = "女" }&lt;br&gt;};  &lt;p&gt;string startVal = string.Empty;&lt;br&gt;var AggNamePerSex = from f in family&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; group f by f.Sex into g&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; select new {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sex = g.Key,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AggName = g.Aggregate(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; startVal // 初期値&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; , (running, next) =&amp;gt; running += next.Name + "," // 集計処理&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; , result =&amp;gt; result == string.Empty ? result : result.Substring(0, result.Length -1) // 終了処理&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };  &lt;p&gt;foreach (var sexGroup in AggNamePerSex)&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(sexGroup.Sex + " : " + sexGroup.AggName);&lt;br&gt;} &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;実行結果はこんな感じ&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2" width="700" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="700"&gt; &lt;p&gt;男 : 父,爺ちゃん&lt;br&gt;女 : 母,娘,曾婆ちゃん,曾曾婆ちゃん&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;処理の方をよく見てみると、初期値（初期化）→集計処理→終了処理　とOracleやSQL Serverと似ていますね。パラレル実行などがないため、マージはありませんが（ｗ&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;P.S. ソースを見てみると、もはやC#のソースに見えない…というか、なぜ「C」って付いているんだろうｗ&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/146658.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>ユーザー定義集計関数：CSV形式で文字列を集計 - SQL Server 2005</title><link>http://blogs.wankuma.com/ganfield/archive/2008/06/30/146270.aspx</link><pubDate>Mon, 30 Jun 2008 01:12:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2008/06/30/146270.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/146270.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2008/06/30/146270.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/146270.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/146270.aspx</trackback:ping><description>&lt;P&gt;&lt;A href="http://blogs.wankuma.com/ganfield/archive/2008/06/22/144865.aspx"&gt;前回&lt;/A&gt;のOracleでユーザ定義集計関数を作成したので、今度はSQL Server 2005で作ってみた。ちなみに、わんくま内のblogを検索してみたらSQL CLRについてのエントリがあまり無い。&lt;/P&gt;
&lt;P&gt;人気茄子&amp;#8230;やろうと思えばDataTableでガリガリやれないこともない&amp;#8230;&lt;/P&gt;
&lt;P&gt;&amp;#8230;&lt;/P&gt;
&lt;P&gt;まあ、これからですよ！これから！ははは&lt;/P&gt;
&lt;P&gt;気を取り直して、SQL CLRで作るユーザ定義集計関数。いってみよー&lt;/P&gt;
&lt;H2&gt;大まかな流れ&lt;/H2&gt;
&lt;P&gt;Oracleの場合と違い、SQL Serverでユーザ定義集計関数を作成する場合、アセンブリを作成する必要がのですが&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;.NETでコーディングしてアセンブリ作成（署名忘れずに※１） 
&lt;LI&gt;1で作成したクラスを紐付けたユーザー定義集計関数を定義&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;と、あまり変わらないじゃん♪　（え？アセンブリを署名するのが面倒？まあ、やらないでもいい方法があるんで♪）&lt;/P&gt;
&lt;H2&gt;ユーザー定義集計関数インターフェース&lt;/H2&gt;
&lt;P&gt;インターフェースというと語弊が若干あるのですが、要する実装する必要があるインターフェース＆定義する必要のあるメソッド及びアトリビュートです。&lt;/P&gt;
&lt;P&gt;クラスに対して必要なもの&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Microsoft.SqlServer.Server.SqlUserDefinedAggregate アトリビュート（クラス）の定義 
&lt;LI&gt;Microsoft.SqlServer.Server.IBinarySerialize インターフェースの継承&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;メンバに対して必要なもの&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;public void Init() 
&lt;LI&gt;public void Accumulate(SqlString value) 
&lt;LI&gt;public void Merge(CsvConcatenation other) 
&lt;LI&gt;public SqlString Terminate() 
&lt;LI&gt;public void Read(BinaryReader r)　※IBinarySerializeの実装 
&lt;LI&gt;public void Write(BinaryWriter w)　※IBinarySerializeの実装&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;うム。上の四つはOracleと一緒だ（笑&lt;/P&gt;
&lt;P&gt;ということで、サクサクいきましょう。&lt;/P&gt;
&lt;H2&gt;CsvConcate集計関数&lt;/H2&gt;
&lt;P&gt;こういう、関数の実装部分を定義するクラスの名前っていつも悩みますね。動詞にするかしないかってことで。今回はSQL Server 2005に登録する関数と同じ名前にしたかったので、CsvConcateにしましたが、クラス名だけならCsvConcatenationにしちゃってもいいんですよね。&lt;/P&gt;
&lt;P&gt;とまあ、クラス名の話はさておき、文字列をCSV形式で集計してくれるユーザー定義集計関数を作りたいと思います。&lt;/P&gt;
&lt;P&gt;まずはMicrosoft.SqlServer.Server.SqlUserDefinedAggregate アトリビュートの定義&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=715 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=713&gt;
&lt;P&gt;[Serializable]&lt;BR&gt;[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Microsoft.SqlServer.Server.Format.UserDefined, //シリアライズ形式（ネイティブかユーザ定義）&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsInvariantToNulls = true,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // NULLに対して不変かどうか（NULLを集計しない場合はTrue）&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsInvariantToDuplicates = false,&amp;nbsp;&amp;nbsp;&amp;nbsp; // 重複値に対して不変かどうか（重複した値を集計しない場合はTrue）&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsInvariantToOrder = false,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 現在は未使用（未実装）&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MaxByteSize = 8000)]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // MAXサイズ&lt;BR&gt;public class CsvConcate : Microsoft.SqlServer.Server.IBinarySerialize&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;定義の内容はコメントの通り。NULLや重複値については用途に合わせて使い分けて下さい。&lt;/P&gt;
&lt;P&gt;次はInit～Treminateまでのメソッドです。&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=717 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=715&gt;
&lt;P&gt;/// &amp;lt;summary&amp;gt;&lt;BR&gt;/// 中間結果を保持&lt;BR&gt;/// &amp;lt;/summary&amp;gt;&lt;BR&gt;private StringBuilder intermediateResult; 
&lt;P&gt;/// &amp;lt;summary&amp;gt;&lt;BR&gt;/// 初期化&lt;BR&gt;/// &amp;lt;/summary&amp;gt;&lt;BR&gt;public void Init()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; intermediateResult = new StringBuilder();&lt;BR&gt;} 
&lt;P&gt;/// &amp;lt;summary&amp;gt;&lt;BR&gt;/// 実際の集計処理&lt;BR&gt;/// &amp;lt;/summary&amp;gt;&lt;BR&gt;/// &amp;lt;param name="value"&amp;gt;&amp;lt;/param&amp;gt;&lt;BR&gt;public void Accumulate(SqlString value)&lt;BR&gt;{ 
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (value.IsNull)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; intermediateResult.Append(string.Empty).Append(',');&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; intermediateResult.Append(value.Value).Append(','); 
&lt;P&gt;} 
&lt;P&gt;/// &amp;lt;summary&amp;gt;&lt;BR&gt;/// 部分計算された場合のマージ&lt;BR&gt;/// &amp;lt;/summary&amp;gt;&lt;BR&gt;/// &amp;lt;param name="other"&amp;gt;&amp;lt;/param&amp;gt;&lt;BR&gt;public void Merge(CsvConcate other)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; intermediateResult.Append(other.intermediateResult);&lt;BR&gt;} 
&lt;P&gt;/// &amp;lt;summary&amp;gt;&lt;BR&gt;/// 終了処理&lt;BR&gt;/// &amp;lt;/summary&amp;gt;&lt;BR&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;BR&gt;public SqlString Terminate()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; string output = string.Empty;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 最後のカンマはおさらば&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (intermediateResult != null &amp;amp;&amp;amp; intermediateResult.Length &amp;gt; 0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output = intermediateResult.ToString(0, intermediateResult.Length - 1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new SqlString(output);&lt;BR&gt;}&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;そんでもってIBinarySerialize インターフェースの実装(Microsoft.SqlServer.Server.Format.Nativeの場合は必要なし？)&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=710 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=708&gt;
&lt;P&gt;#region IBinarySerialize メンバ 
&lt;P&gt;void IBinarySerialize.Read(BinaryReader r)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (r == null) throw new ArgumentNullException("r");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; intermediateResult = new StringBuilder(r.ReadString());&lt;BR&gt;} 
&lt;P&gt;void IBinarySerialize.Write(BinaryWriter w)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (w == null) throw new ArgumentNullException("w");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; w.Write(intermediateResult.ToString());&lt;BR&gt;} 
&lt;P&gt;#endregion&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;アセンブリを署名するのを忘れずに（キーペアは「sn」などで作成しましょう）※１&lt;/P&gt;
&lt;H2&gt;&lt;/H2&gt;
&lt;H2&gt;&lt;/H2&gt;
&lt;H2&gt;&lt;/H2&gt;
&lt;H2&gt;ユーザー定義集計関数の登録&lt;/H2&gt;
&lt;P&gt;さて、署名付きのアセンブリが作成できたのなら、あとは登録するだけです。とりあえず、やることは三つ&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;アセンブリの登録 
&lt;LI&gt;ユーザー定義集計関数の定義（クラスとの紐付け）&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;登録するアセンブリの配置場所ですが、こいつは適当「UserLib」に切っておいて、そこに作成したアセンブリ「StringUtility.dll」を配置します。&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=706 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=704&gt;C:\Program Files\Microsoft SQL Server\90\UserLib\StringUtility.dll&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;（別にSQL Serverと同じフォルダでなくても構いません。）&lt;/P&gt;
&lt;P&gt;それと、CLR統合機能を予め有効化する必要があるので、以下のSQLを発行(参考文献：夏椰さんのを参照）&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=700 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=700&gt;sp_configure 'clr enabled', 1&lt;BR&gt;GO&lt;BR&gt;RECONFIGURE&lt;BR&gt;GO&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;あとはこいつを登録してやるだけです。以下のSQLを発行&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=700 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=700&gt;
&lt;P&gt;-- アセンブリのパス&lt;BR&gt;declare @asmblyPath nvarchar(1000)&lt;BR&gt;set @asmblyPath = 'C:\Program Files\Microsoft SQL Server\90\UserLib\StringUtility.dll' 
&lt;P&gt;-- アセンブリの登録&lt;BR&gt;CREATE ASSEMBLY StringUtility FROM @asmblyPath&lt;BR&gt;WITH permission_set=Safe;&lt;BR&gt;GO 
&lt;P&gt;-- ユーザー定義集計関数の定義&lt;BR&gt;CREATE AGGREGATE Concatenate(@input nvarchar(4000))&lt;BR&gt;RETURNS nvarchar(4000)&lt;BR&gt;EXTERNAL NAME [StringUtility].[Wankuma.Ganf.SqlClr.StringUtility.CsvConcate];&lt;BR&gt;GO&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;これで、完成。では実際にNorthWindで使ってみましょう。（AdventureWorksでもいいですが、あれは結構件数が入っているので、バッファがすぐにあふry）&lt;/P&gt;
&lt;H2&gt;使い方&lt;/H2&gt;
&lt;P&gt;こちらも、Oracle同様、他の集計関数と同じ使い方です。&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=700 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=700&gt;
&lt;P&gt;select country, dbo.csvconcate(employeeid) &lt;BR&gt;from employees group by country&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;H2&gt;&lt;/H2&gt;
&lt;H2&gt;参考文献&lt;/H2&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/ja-jp/library/ms131051.aspx"&gt;MSDN CLR ユーザー定義集計の要件&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A title=http://technet.microsoft.com/ja-jp/library/ms161551.aspx href="http://technet.microsoft.com/ja-jp/library/ms161551.aspx"&gt;http://technet.microsoft.com/ja-jp/library/ms161551.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;ユーザー定義集計関とは違いますが、数夏椰さんのとこでいくつかSQL CLRが公開されています。&lt;/P&gt;
&lt;P&gt;&lt;A href="http://kaya.wankuma.com/box/Default.aspx"&gt;夏椰の庵 - Secluded Spot of Kaya - BOX&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;※１　アセンブリの署名を行わなくても、アセンブリの登録は可能です。その場合は、データベースのTRUSTWORTHYをONにしましょう。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/146270.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>MVC - モデルビューコントローラ</title><link>http://blogs.wankuma.com/ganfield/archive/2007/07/16/85332.aspx</link><pubDate>Mon, 16 Jul 2007 12:21:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2007/07/16/85332.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/85332.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2007/07/16/85332.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/85332.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/85332.aspx</trackback:ping><description>&lt;P&gt;仕事でMVCやプレゼンテーション部分のアーキパターンについての話題が挙がったので、真面目に調べてみました。ということでノート代わりにここを使用します。間違っていたら指摘して下さいね。&lt;/P&gt;
&lt;H4&gt;1. 発祥&lt;/H4&gt;
&lt;P&gt;1978年にSmalltalkを開発していたXerox社の研究所で生まれる。その後、MVCの実装を記述した論文「&lt;I&gt;Applications Programming in Smalltalk-80(TM):How to use Model-View-Controller&lt;/I&gt;」が発表されるとその有用性から多方面へと広がる。&lt;/P&gt;
&lt;H4&gt;2. 構造&lt;/H4&gt;
&lt;P&gt;UIの構造やビジネスロジック（データ含む）などの利害関係の異なるそれぞれの要素に対し、どのようにすればそれらを奇麗に分離することができるのか？という問題に対する一つの解として登場したのがMVCです。MVCではビジネスロジックやUI、ユーザからの入力の三つ(つまり、処理/出力/入力)をそれぞれModel/View/Controllerの3つの要素に分離し、役割を設けます。&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=600 border=1 unselectable="on"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;Model&lt;/TD&gt;
&lt;TD vAlign=top width=491&gt;ドメイン（ドメインレイヤーではない）についての情報や捜査を担当する要素。主にビジネスロジックを実装します。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;View&lt;/TD&gt;
&lt;TD vAlign=top width=491&gt;ユーザへの情報の表示を担当する要素（UI）。Modelのデータを出力します。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=107&gt;Controller&lt;/TD&gt;
&lt;TD vAlign=top width=491&gt;ユーザからのアクションを受け、ModelやViewの操作を担当する要素。&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;&lt;A href="http://ganfield.wankuma.com/blog/img/2007/MVC_AD98/ModelViewControllerDiagram_svg.png" atomicselection="true"&gt;&lt;IMG style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=112 alt=ModelViewControllerDiagram_svg src="http://ganfield.wankuma.com/blog/img/2007/MVC_AD98/ModelViewControllerDiagram_svg_thumb.png" width=240 border=0&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;※　実線は直接的な関連性、点線は間接的な関連性を示す。&lt;/P&gt;
&lt;H4&gt;3. 分離と依存性&lt;/H4&gt;
&lt;P&gt;MVCの最も重要な点として、Presentation(ViewとController)とModelの分離が挙げられます。ModelをPresentationから独立させ、更にPresentationに依存させないことにより次のメリットが得られます。&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Modelにおける処理が簡素化される。 
&lt;LI&gt;Model単体でテストを行うことが可能である。非UI要素なので、単体テストも比較的容易に可能である。 
&lt;LI&gt;Presentationの修正をModelをいじらずに行うことが可能となる。&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;尚、Modelに関しては「Passive Model」と呼ばれるパターンと「Active Model」と呼ばれる二つのパターンが存在します。Passive ModelはModelがControllerによって排他的に使用される場合は使用することができます。例えば、Webアプリケーションなどは基本Modelのデータは顧客単位で保持している場合が多く、この場合ModelはControllerより（実質的に）排他的に利用されると考えてよい。とうぜんModelを共有する可能性が出てくる場合もあるが、楽観ロックや悲観ロック等で同時実行制御を行うことで問題を回避することができる。&lt;/P&gt;
&lt;P&gt;一方、複数のViewからModelを参照し、そのどれかのControllerによりModelが更新され、その更新を各Viewに反映する必要がある場合Passive Modelを使用することはできません。Modelの変更をController抜きにViewへ反映する必要がある場合、「Active Model」を使用することになります。Active Modelでは、Modelの変更をViewに反映する必要があることから、Modelに依存しているViewを管理するどこかで必要があります。Model要素にView要素への直接的な依存性を持たせてしまうと、Model View Controllerと分離させた意味が無くなってしまうので、依存性を管理するコレクションを利用したり、Observerパターンを利用することによりViewとModelの直接的な依存性を回避する必要があります。&lt;/P&gt;
&lt;P&gt;（ちなみに、この辺でよくある勘違いとして、PresentationがModelに依存しないと思ってしまう人がいます。これは大きな間違いで、PresentationとModelは分離しても、PresentationからModelへの依存性は必ず発生します。重要なのは&lt;STRONG&gt;ModelからPresentationへの依存性を無くすこと&lt;/STRONG&gt;です。というか、依存性無しじゃプログラム作れないよっ）&lt;/P&gt;
&lt;P&gt;もう一つViewとControllerの分離もありますが、こちらはPresentationとModelの分離ほど重要視されていません。これはViewとControllerを明確に分離すること自体難しい場合が多いからです。（ただWebアプリケーションなどはそうも言ってられないみたいですが&amp;#8230;）&lt;/P&gt;
&lt;H4&gt;&lt;/H4&gt;
&lt;P&gt;4. MVCの実装と派生パターン&lt;/P&gt;
&lt;P&gt;MVCの実装方法としてはPage ControllerやFront Controllerパターン、MVCからの派生パターンとしてMVP(Model View Presenter&amp;nbsp;)があります。が、まだしっかりと調べきっていないので、また次の機会に説明します(；&amp;#180;Д｀)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H4&gt;参考文献&lt;/H4&gt;
&lt;P&gt;[1] &lt;A href="http://en.wikipedia.org/wiki/Model-view-controller"&gt;Model-view-controller wiki&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;[2] &lt;A href="http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html"&gt;MVC - XEROX PARC 1978-79&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;[3] &lt;A href="http://st-www.cs.uiuc.edu/users/smarch/st-docs/mvc.html"&gt;Applications Programming in Smalltalk-80(TM) : How to use Model-View-Controller&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;[4] &lt;A href="http://www.microsoft.com/japan/msdn/practices/type/Patterns/enterprise/desmvc.aspx"&gt;モデルビューコントローラ MSDN&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;[5] Martin Fowler, エンタープライズアーキテクチャパターン,&amp;nbsp;ISBN4-7981-0553-8&lt;/P&gt;
&lt;P&gt;[6] GoF, デザインパターン, ISBN4-7973-1112-6&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;# 書き始めたころに大きな地震がありました。またもや新潟らしいです。北陸地方の人大丈夫ですかね&amp;#8230;&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/85332.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>70-528げっつ。ついでにロゴもげっつ</title><link>http://blogs.wankuma.com/ganfield/archive/2007/04/27/73520.aspx</link><pubDate>Fri, 27 Apr 2007 18:13:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2007/04/27/73520.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/73520.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2007/04/27/73520.aspx#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/73520.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/73520.aspx</trackback:ping><description>&lt;P&gt;70-528を無事ゲット。某動画サイトで長編シリーズものにハマり、勉強時間減って危うく落ちるとこでしたが無事取得。&lt;/P&gt;
&lt;P&gt;折角だからMCTSのロゴが欲しいな～なんて思って海外サイトを散歩してみたら、英語の方のMCPメンバサイトに&lt;/P&gt;
&lt;P&gt;ロゴビルダーなんてのがありました。便利です。ただ、取得したばかりの資格はまだMSの方にデータが届いていないためか&lt;/P&gt;
&lt;P&gt;作れませんでした。残念。orz&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;# ロゴビルダーで作ったロゴって余白が無いのねん&lt;/P&gt;
&lt;P&gt;# 50-528になっていたので70-528に修正&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/73520.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>レッツら Windows Communication Foundation - インスタンスのライフサイクル</title><link>http://blogs.wankuma.com/ganfield/archive/2007/04/15/71480.aspx</link><pubDate>Sun, 15 Apr 2007 00:50:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2007/04/15/71480.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/71480.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2007/04/15/71480.aspx#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/71480.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/71480.aspx</trackback:ping><description>&lt;P&gt;わんくま勉強会＃６のかるぼさんのセッションにインスパイアされて調べました。キッカケはかるぼさんがCountUpというWebMethod(WCFではOperationContract)を作った時、フィールドに値を保持しようとしていたことです。（ちなみに、下記の内容はほとんどセッション後に話してたものだったりしますｗ）&lt;/P&gt;
&lt;P&gt;　&lt;/P&gt;
&lt;P&gt;まず、WCFのインスタンスのライフサイクルを説明する前に、WCFが登場する以前の.NET RemotingだったりWebサービス(asmx)のインスタンスのライフサイクルをおさらいしたいと思います。&lt;/P&gt;
&lt;P&gt;といったところで、いくつもあるわけではないのでサクっと行きます。&lt;/P&gt;
&lt;P&gt;　&lt;/P&gt;
&lt;P&gt;１．要求ごとにインスタンスを生成する。&lt;/P&gt;
&lt;P&gt;WebサービスやASP.NETがこのタイプです。.NET Remoting も設定でこのタイプを指定することができます。&lt;/P&gt;
&lt;P&gt;　&lt;/P&gt;
&lt;P&gt;２．インスタンスを一つだけ生成する。（Singleton）&lt;/P&gt;
&lt;P&gt;.NET Remotingは設定でこのタイプを指定することができます。&lt;/P&gt;
&lt;P&gt;　&lt;/P&gt;
&lt;P&gt;この二つのパターンがあります。&lt;/P&gt;
&lt;P&gt;では、WCFではどうなったかというと、上記の二つに加え、&lt;STRONG&gt;セッションごとにインスタンスを生成する&lt;/STRONG&gt;というものが増えています。つまり、&lt;/P&gt;
&lt;P&gt;　&lt;/P&gt;
&lt;P&gt;３．セッションごとにインスタンスを生成する。&lt;/P&gt;
&lt;P&gt;　&lt;/P&gt;
&lt;P&gt;というのが3つ目の選択肢がWCFで新たに追加されています。簡単に言ってしまえば、クライアントごとにインスタンスを生成するというもので、ステートフルなサービスを作ることができます。ASP.NETのセッションと同じですね。設定方法は以下の通り&lt;/P&gt;
&lt;P&gt;　&lt;/P&gt;
&lt;P&gt;[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]&lt;BR&gt;public class MyService : IMyService 
&lt;P&gt;　 
&lt;P&gt;IMyServiceはServiceContract、つまりサービスとして公開するインターフェースです。MyServiceはその実装で、その実装クラスにServiceBehaviorAttributeを付け、InstanceContextMode=InstanceContextMode.PerSessionを設定します。InstanceContextModeの列挙体は上記の説明からわかるように三つの値があります。 
&lt;P&gt;　&lt;/P&gt;
&lt;P&gt;InstanceContextMode.PerCall&lt;BR&gt;InstanceContextMode.Singleton&lt;BR&gt;InstanceContextMode.PerSession&lt;/P&gt;
&lt;P&gt;　&lt;/P&gt;
&lt;P&gt;ところで、PerSessionでセッションごとにインスタンスを生成できるのはいいんだけど、サーバを&lt;STRONG&gt;&lt;FONT size=5&gt;クラスタ化&lt;/FONT&gt;&lt;/STRONG&gt;している場合どうするんだろうか&amp;#8230;ASP.NETみたいにDBに状態を保持させたりなんてできるのかな&amp;#8230;それともロードバランサー側でクライアントのセッションが繋がるように割り振れということなのだろうか&amp;#8230;というか、やっぱり分散系のベストプラクティスにあるようにステートレスな設計しなさいってことかな(&amp;#180;・ω・`)ｼｮﾎﾞｰﾝ&lt;/P&gt;
&lt;P&gt;orz&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/71480.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>レッツら Web Services Enhancements 3.0 (WSE 3.0) - 簡単な認証</title><link>http://blogs.wankuma.com/ganfield/archive/2007/04/06/70442.aspx</link><pubDate>Fri, 06 Apr 2007 17:28:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2007/04/06/70442.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/70442.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2007/04/06/70442.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/70442.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/70442.aspx</trackback:ping><description>&lt;P&gt;　SOAPをHTTPにバインディングしている限り不要とも思えるWSE。しかし、WCFにも組み込まれると言われれば無視することもできません（？）。一応Amazon Web Serviceでも少し使っているみたいだし、どんなことができるのか調べてみましょう。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H5&gt;WSE 3.0 のインストール&lt;/H5&gt;
&lt;P&gt;&lt;A href="http://www.microsoft.com/downloads/details.aspx?familyid=018a09fd-3a74-43c5-8ec1-8d789091255d&amp;amp;displaylang=en"&gt;Web Services Enhancements (WSE) 3.0 for Microsoft .NET&lt;/A&gt; からダウンロードしてインストール。尚、インストールする前に一度もVisual Studio 2005 を起動したことがないと、ソリューションエクスプローラのコンテキストメニューに[WSE Setting 3.0]が表示されないみたいです。再インストール時には気をつけねば&amp;#8230; 
&lt;DIV style="BORDER-RIGHT: gray 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: gray 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; BORDER-LEFT: gray 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: gray 1px solid"&gt;さらに注意：VistaのVisual Studio 2005 のコンテキストメニューに[WSE Setting 3.0]が表示させるにはマニュアルでアドインを追加するしかないみたいです。何度かインストールとアンインストールを繰り返して試してみたのですがダメでした。ユーザのフォルダ構成が変わったからかもしれません。C:\Users\ganfield\Documents\Visual Studio 2005にAddinsフォルダを作成し、その中にWindows XP等から持ってきたアドインファイルをコピったらコンテキストメニューに[WSE Setting 3.0]が表示されました。アドインファイルはC:\Documents and Settings\All Users\Application Data\Microsoft\MSEnvShared\Addinsにあります。（ここ以外の場合もあります。詳しくはVisual Studio 2005 の[オプション]のアドインファイルパスを参照） &lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H5&gt;WSE 3.0 を使ったWebサービスサーバ&lt;/H5&gt;
&lt;OL&gt;
&lt;LI&gt;[新規作成]→[Webサイト]からASP.NET Webサービスを作成します。 
&lt;LI&gt;参照にMicrosoft.Web.Service3を追加します。 
&lt;LI&gt;[ソリューションエクスプローラ]から[WSE Setting 3.0]を起動します。 
&lt;LI&gt;[General]タブで[Enable this project for Web Services Enhancements]と[Enable Microsoft Web Services Enhancement SOAP Protocol Factory]のチェックボックスをオンにする。 
&lt;LI&gt;[Policy]タブで[Enable Policy]チェックボックスをオンにし、[Edit Application Policy]パネルにある[Add]ボタンを押す。Policyの名前を「UsernameServerPolicy」とし、[OK]を押す。 
&lt;LI&gt;新たに出てきたダイログボックスで[Next]を押し、Authentication Settings画面で[Secure a service application]と[username]ラジオボタンをオンにし、[Next]を押す。 
&lt;LI&gt;User and Roles画面で、[Perform Authorization]チェックボックスをオンにし、アクセス権を与えるユーザを選び、[Next]を押す。ユーザ名はしっかりと「コンピュータ名\ユーザ名」で記述する必要があります。 
&lt;LI&gt;Message Protection画面で[Protection Order]の[None]ラジオボタンをオンにし、[Next]を押します。 
&lt;LI&gt;Create Secure Settings画面で設定を確認したら[Finish]を押します。 
&lt;LI&gt;Web.configの内容とwse3policyCache.configファイルが自動生成されます。 
&lt;LI&gt;WebサービスのクラスにPolicyAttributeを付与します。Policy名は先ほど作成したUsernameServerPolicyを使用します。 &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;[WebService(Namespace = "http://ganfield.website4.org/")] 
&lt;P&gt;[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
&lt;P&gt;[Policy("UsernameServerPolicy")] 
&lt;P&gt;public class Service : System.Web.Services.WebService 
&lt;P&gt;
&lt;P&gt;&lt;STRONG&gt;サーバ側のコード&lt;/STRONG&gt; &lt;PRE&gt;using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using Microsoft.Web.Services3;
 
[WebService(Namespace = "http://ganfield.website4.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[Policy("UsernameServerPolicy")]
public class Service : System.Web.Services.WebService
{
    public Service () {
    }
 
    [WebMethod]
    public string HelloWorld(string name) {
        return "Hello World " + name + " !!";
    }
    
}
&lt;/PRE&gt;
&lt;P&gt;
&lt;P&gt;&lt;STRONG&gt;web.config&lt;/STRONG&gt; &lt;PRE&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;configuration&amp;gt;
  &amp;lt;configSections&amp;gt;
    &amp;lt;section name="microsoft.web.services3" type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
  &amp;lt;/configSections&amp;gt;
  &amp;lt;system.web&amp;gt;
    &amp;lt;webServices&amp;gt;
      &amp;lt;soapExtensionImporterTypes&amp;gt;
        &amp;lt;add type="Microsoft.Web.Services3.Description.WseExtensionImporter, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
      &amp;lt;/soapExtensionImporterTypes&amp;gt;
      &amp;lt;soapServerProtocolFactory type="Microsoft.Web.Services3.WseProtocolFactory, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
    &amp;lt;/webServices&amp;gt;
    &amp;lt;compilation debug="true"&amp;gt;
      &amp;lt;assemblies&amp;gt;
        &amp;lt;add assembly="Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /&amp;gt;
        &amp;lt;!--&amp;lt;add assembly="Microsoft.Web.Services2, Version=2.0.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /&amp;gt;--&amp;gt;
      &amp;lt;/assemblies&amp;gt;
    &amp;lt;/compilation&amp;gt;
  &amp;lt;/system.web&amp;gt;
  &amp;lt;microsoft.web.services3&amp;gt;
    &amp;lt;security&amp;gt;
    &amp;lt;/security&amp;gt;
    &amp;lt;policy fileName="wse3policyCache.config" /&amp;gt;
  &amp;lt;/microsoft.web.services3&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/PRE&gt;
&lt;P&gt;
&lt;P&gt;&lt;STRONG&gt;wse3policyCache.config&lt;/STRONG&gt; &lt;PRE&gt;&amp;lt;policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy"&amp;gt;
  &amp;lt;extensions&amp;gt;
    &amp;lt;extension name="authorization" type="Microsoft.Web.Services3.Design.AuthorizationAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
    &amp;lt;extension name="usernameForCertificateSecurity" type="Microsoft.Web.Services3.Design.UsernameForCertificateAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
    &amp;lt;extension name="x509" type="Microsoft.Web.Services3.Design.X509TokenProvider, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
    &amp;lt;extension name="requireActionHeader" type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
    &amp;lt;extension name="usernameOverTransportSecurity" type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
  &amp;lt;/extensions&amp;gt;
  &amp;lt;policy name="UsernameServerPolicy"&amp;gt;
    &amp;lt;authorization&amp;gt;
      &amp;lt;allow user="コンピュータ名\ユーザ名" /&amp;gt;
      &amp;lt;deny user="*" /&amp;gt;
    &amp;lt;/authorization&amp;gt;
    &amp;lt;usernameOverTransportSecurity /&amp;gt;
    &amp;lt;requireActionHeader /&amp;gt;
  &amp;lt;/policy&amp;gt;
&amp;lt;/policies&amp;gt;
&lt;/PRE&gt;
&lt;P&gt;
&lt;H5&gt;WSE 3.0 を使ったWebサービスクライアント&lt;/H5&gt;
&lt;OL&gt;
&lt;LI&gt;[新規作成]→[プロジェクト]からコンソールアプリを作成します。 
&lt;LI&gt;Web参照にWebサービスを追加します。 
&lt;LI&gt;参照にMicrosoft.Web.Service3を追加します。 
&lt;LI&gt;[ソリューションエクスプローラ]で[すべてをファイルを表示]をオンにし、[Web Reference]の中からReference.csを探し出し、コードを表示します。 
&lt;LI&gt;Reference.csのプロキシクラスのスーパークラスをMicrosoft.Web.Services3.WebServicesClientProtocolに変更します。(プロキシクラスにサービス名 + Wseというクラスがある場合、5．の作業は飛ばして下さい。WSDLツールがWSEに対応したクラスを自動生成しています。) 
&lt;LI&gt;[ソリューションエクスプローラ]から[WSE Setting 3.0]を起動します。 
&lt;LI&gt;[General]タブで[Enable this project for Web Services Enhancements]チェックボックスをオンにする。 
&lt;LI&gt;[Policy]タブで[Enable Policy]チェックボックスをオンにし、[Edit Application Policy]パネルにある[Add]ボタンを押す。Policyの名前を「UsernameClientPolicy」とし、[OK]を押す。 
&lt;LI&gt;新たに出てきたダイログボックスで[Next]を押し、Authentication Settings画面で[Secure a client application]と[username]ラジオボタンをオンにし、[Next]を押す。 
&lt;LI&gt;Optionally provide Username and Password画面で、ユーザ名とパスワードを入力し、[Next]を押す。ユーザ名の前にコンピュータ名を記述する必要はありません。 
&lt;LI&gt;Message Protection画面で[Protection Order]の[None]ラジオボタンをオンにし、[Next]を押します。 
&lt;LI&gt;Create Secure Settings画面で設定を確認したら[Finish]を押します。 
&lt;LI&gt;app.configの内容とwse3policyCache.configファイルが自動生成されます。 
&lt;LI&gt;プロキシクラスのSetPolicyメソッドを使用してPolicyを設定します。Policy名は先ほど作成したUsernameClientPolicyを使用します。 proxy.SetPolicy("UsernameClientPolicy"); 
&lt;LI&gt;ビルドして実行する。 &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;
&lt;P&gt;&lt;STRONG&gt;クライアント側のコード&lt;/STRONG&gt; &lt;PRE&gt;using System;
using System.Collections.Generic;
using System.Text;
 
namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            WebSite4.SampleServiceWse proxy = new WebSite4.SampleServiceWse();
            proxy.SetPolicy("UsernameClientPolicy");
            Console.WriteLine(proxy.HelloWorld("aaa"));
            Console.ReadLine();
        }
    }
}

&lt;/PRE&gt;
&lt;P&gt;
&lt;P&gt;&lt;STRONG&gt;app.config&lt;/STRONG&gt;&lt;PRE&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;configuration&amp;gt;
  &amp;lt;configSections&amp;gt;
    &amp;lt;sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"&amp;gt;
      &amp;lt;section name="ConsoleApplication2.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /&amp;gt;
    &amp;lt;/sectionGroup&amp;gt;
    &amp;lt;section name="microsoft.web.services3" type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
  &amp;lt;/configSections&amp;gt;
  &amp;lt;applicationSettings&amp;gt;
    &amp;lt;ConsoleApplication2.Properties.Settings&amp;gt;
      &amp;lt;setting name="ConsoleApplication2_WebReference_Service" serializeAs="String"&amp;gt;
        &amp;lt;value&amp;gt;http://192.168.xx.yy/testwebroot/website4/SampleService.asmx&amp;lt;/value&amp;gt;
      &amp;lt;/setting&amp;gt;
    &amp;lt;/ConsoleApplication2.Properties.Settings&amp;gt;
  &amp;lt;/applicationSettings&amp;gt;
  &amp;lt;microsoft.web.services3&amp;gt;
    &amp;lt;policy fileName="wse3policyCache.config" /&amp;gt;
  &amp;lt;/microsoft.web.services3&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/PRE&gt;
&lt;P&gt;
&lt;P&gt;&lt;STRONG&gt;wse3policyCache.config&lt;/STRONG&gt; &lt;PRE&gt;&amp;lt;policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy"&amp;gt;
  &amp;lt;extensions&amp;gt;
    &amp;lt;extension name="usernameOverTransportSecurity" type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
    &amp;lt;extension name="username" type="Microsoft.Web.Services3.Design.UsernameTokenProvider, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
    &amp;lt;extension name="requireActionHeader" type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt;
  &amp;lt;/extensions&amp;gt;
  &amp;lt;policy name="UsernameClientPolicy"&amp;gt;
    &amp;lt;usernameOverTransportSecurity&amp;gt;
      &amp;lt;clientToken&amp;gt;
        &amp;lt;username username="ユーザ名" password="ひ・み・つ" /&amp;gt;
      &amp;lt;/clientToken&amp;gt;
    &amp;lt;/usernameOverTransportSecurity&amp;gt;
    &amp;lt;requireActionHeader /&amp;gt;
  &amp;lt;/policy&amp;gt;
&amp;lt;/policies&amp;gt;
&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;SOAP Request&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;TEXTAREA rows=10 cols=100&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt; &amp;lt;soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"&amp;gt; &amp;lt;soap:Header&amp;gt; &amp;lt;wsa:Action&amp;gt;http://ganfield.website4.org/HelloWorld&amp;lt;/wsa:Action&amp;gt; &amp;lt;wsa:MessageID&amp;gt;urn:uuid:a51cc49c-29c8-4527-8deb-363869783c4f&amp;lt;/wsa:MessageID&amp;gt; &amp;lt;wsa:ReplyTo&amp;gt;&amp;lt;wsa:Address&amp;gt;http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous&amp;lt;/wsa:Address&amp;gt;&amp;lt;/wsa:ReplyTo&amp;gt; &amp;lt;wsa:To&amp;gt;http://192.168.xx.yy/testwebroot/WebSite4/SampleService.asmx&amp;lt;/wsa:To&amp;gt; &amp;lt;wsse:Security soap:mustUnderstand="1"&amp;gt; &amp;lt;wsu:Timestamp wsu:Id="Timestamp-74c3a4e2-9923-40ad-93d0-3147406af0e1"&amp;gt; &amp;lt;wsu:Created&amp;gt;2007-04-06T06:48:48Z&amp;lt;/wsu:Created&amp;gt; &amp;lt;wsu:Expires&amp;gt;2007-04-06T06:53:48Z&amp;lt;/wsu:Expires&amp;gt;&amp;lt;/wsu:Timestamp&amp;gt; &amp;lt;wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-250c3a6d-4c57-4d67-acc3-953edf5ef386"&amp;gt;&amp;lt;wsse:Username&amp;gt;ユーザ名&amp;lt;/wsse:Username&amp;gt; &amp;lt;wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"&amp;gt;ひ・み・つ&amp;lt;/wsse:Password&amp;gt; &amp;lt;wsse:Nonce&amp;gt;bzctbWS0X4c171/2qEIN1Q==&amp;lt;/wsse:Nonce&amp;gt;&amp;lt;wsu:Created&amp;gt;2007-04-06T06:48:48Z&amp;lt;/wsu:Created&amp;gt; &amp;lt;/wsse:UsernameToken&amp;gt; &amp;lt;/wsse:Security&amp;gt; &amp;lt;/soap:Header&amp;gt; &amp;lt;soap:Body&amp;gt;&amp;lt;HelloWorld xmlns="http://ganfield.website4.org/"&amp;gt;&amp;lt;name&amp;gt;aaa&amp;lt;/name&amp;gt;&amp;lt;/HelloWorld&amp;gt;&amp;lt;/soap:Body&amp;gt; &amp;lt;/soap:Envelope&amp;gt; &lt;/TEXTAREA&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;SOAP Response&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;TEXTAREA rows=10 cols=100&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt; &amp;lt;soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"&amp;gt; &amp;lt;soap:Header&amp;gt; &amp;lt;wsa:Action&amp;gt;http://ganfield.website4.org/HelloWorldResponse&amp;lt;/wsa:Action&amp;gt; &amp;lt;wsa:MessageID&amp;gt;urn:uuid:37747218-30ca-4ee7-94e2-38a368f84f7c&amp;lt;/wsa:MessageID&amp;gt;&amp;lt;wsa:RelatesTo&amp;gt;urn:uuid:a51cc49c-29c8-4527-8deb-363869783c4f&amp;lt;/wsa:RelatesTo&amp;gt;&amp;lt;wsa:To&amp;gt;http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous&amp;lt;/wsa:To&amp;gt; &amp;lt;wsse:Security&amp;gt; &amp;lt;wsu:Timestamp wsu:Id="Timestamp-7ae96393-a056-49c9-9b4d-5032d47c1759"&amp;gt; &amp;lt;wsu:Created&amp;gt;2007-04-06T06:49:00Z&amp;lt;/wsu:Created&amp;gt; &amp;lt;wsu:Expires&amp;gt;2007-04-06T06:54:00Z&amp;lt;/wsu:Expires&amp;gt; &amp;lt;/wsu:Timestamp&amp;gt; &amp;lt;/wsse:Security&amp;gt; &amp;lt;/soap:Header&amp;gt; &amp;lt;soap:Body&amp;gt;&amp;lt;HelloWorldResponse xmlns="http://ganfield.website4.org/"&amp;gt;&amp;lt;HelloWorldResult&amp;gt;Hello World aaa !!&amp;lt;/HelloWorldResult&amp;gt;&amp;lt;/HelloWorldResponse&amp;gt;&amp;lt;/soap:Body&amp;gt; &amp;lt;/soap:Envelope&amp;gt;  &lt;/TEXTAREA&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;今回は簡単な認証ということで、UsernameTokenを使用してWebサービスを拡張しましたが、この他にもセキュリティトークンとしてX509SecurityTokenやKerberosToken等があります。また、独自のセキュリティトークンを作成し、使用することもできます。相互運用面に関しては調査しないといけないかもしれませんが、よりセキュアなWebサービスを、と思う方は一度使ってみてはいかがでしょうか？ 
&lt;P&gt;え？SSL＋クライアント証明書で十分？ソンナ、ソンナ&amp;#8230;ｗ &lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/70442.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>ActiveX コントロールを.NETで使う</title><link>http://blogs.wankuma.com/ganfield/archive/2007/03/13/66556.aspx</link><pubDate>Tue, 13 Mar 2007 20:52:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2007/03/13/66556.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/66556.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2007/03/13/66556.aspx#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/66556.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/66556.aspx</trackback:ping><description>&lt;P&gt;ActiveXのコントロールって使いたくなることってありませんか？Vistaはまだ使ったことがないのですが、XPぐらいではまだまだActiveXやCOMは健在で、面白そうなライブラリがゴロゴロ転がっています。COMを.NETで使用する場合、[参照の追加]から[COM]タブを開き、目的のCOMを選べば勝手にラッパークラスを作ってくれて使用することができます。一方、ActiveX コントロールはどうかというと、当然.NETのControlクラスを継承しているはずがないので、単純に参照に追加するだけでは使えません。&lt;/P&gt;
&lt;P&gt;では、どうするか？&lt;/P&gt;
&lt;P&gt;実は.NET FrameworkツールにActiveX コントロール インポータ(Aximp)というのがあります。.NET便利っすねー。すんばらすぃ。ぃよっ、大将！（謎&lt;/P&gt;
&lt;P&gt;使い方も簡単で、例えばWindows Media PlayerのActiveXコントロールのラッパークラスを作ろうとするときは&lt;/P&gt;
&lt;P&gt;aximp c:\WINDOWS\system32\msdxm.ocx&lt;/P&gt;
&lt;P&gt;とVS2005コマンドプロンプトに打ち込んでやれば、&lt;/P&gt;
&lt;P&gt;MediaPlayer.dll&lt;BR&gt;AxMediaPlayer.dll 
&lt;P&gt;の二つのラッパークラスライブラリができあがります。（aximpを実行したときにActiveXが見つからないと言われたら、regsvr32でActiveXをレジストリに登録しましょう。）MediaPlayer.dllは[参照の追加]でCOMを追加した際に作られるラッパークラスライブラリと同じものです。目的のActiveXコントロールラッパークラスライブラリはAxMediaPlayer.dllです。 
&lt;P&gt;AxMediaPlayerも出来上がったことですし、簡単なアプリを作ってみましょう。 
&lt;P&gt;アプリは設定ファイルに書かれているファイルパスからファイルを読み込んで、.NET Form上に設置されたWindowsMediaPlayerコントロールに映像を表示します。 
&lt;P&gt;
&lt;P&gt;コード 
&lt;P&gt;public partial class Form1 : Form&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; &lt;FONT color=#ff0000&gt;AxMediaPlayer.AxMediaPlayer player;&lt;/FONT&gt; 
&lt;P&gt;&amp;nbsp; public Form1()&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; InitializeComponent(); 
&lt;P&gt;&lt;FONT color=#ff0000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; player = new AxMediaPlayer.AxMediaPlayer();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((ISupportInitialize)player).BeginInit();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; player.Dock = DockStyle.Fill;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((ISupportInitialize)player).EndInit(); &lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#ff0000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.Controls.Add(player);&lt;/FONT&gt; 
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.Load += new EventHandler(Form1_Load);&lt;BR&gt;&amp;nbsp; } 
&lt;P&gt;&amp;nbsp; void Form1_Load(object sender, EventArgs e)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&lt;FONT color=#ff0000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; player.FileName =&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WindowsApplication27.Properties.Settings.Default.fileName;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; player.Play();&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;} 
&lt;P&gt;
&lt;P&gt;これで完了。実行結果はこんな感じ 
&lt;P&gt;&lt;IMG src="http://ganfield.wankuma.com/blog/20070313/msdxm_net.jpg"&gt; 
&lt;P&gt;&lt;S&gt;表示されている映像が見えていませんが、&lt;/S&gt;フォームにMediaPlayerのコントロールが表示されているのは分かりますね。&lt;S&gt;（何故見えていないかは謎&amp;#8230;フレームレートのせい？ブラウン管の映像を撮ってるわけじゃあるまいし&amp;#8230;）&lt;/S&gt;&lt;BR&gt;修正：ハードウェアクセラレータをオフにしたらコピペできるようになりました。実験のために無理やり起こされ、不機嫌ななうら助手が写っております。さんきゅー、ぽぴ王子
&lt;P&gt;&amp;nbsp;ActiveXのコントロールはそれこそ.NETのコントロール以上豊富なので、色々使って試したい方は是非aximpでガンガンインポートして使っちゃいましょう。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Reference&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/ja-jp/library/8ccdh774(vs.80).aspx"&gt;Windows フォーム ActiveX コントロール インポータ&lt;/A&gt;&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/66556.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>Amazon Simple Storage Service その４ - DIME Attachment と拡張 -</title><link>http://blogs.wankuma.com/ganfield/archive/2007/03/07/65352.aspx</link><pubDate>Wed, 07 Mar 2007 00:37:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2007/03/07/65352.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/65352.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2007/03/07/65352.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/65352.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/65352.aspx</trackback:ping><description>&lt;P&gt;&lt;/P&gt;
&lt;H3&gt;DIME Attachments S3 Bucket Browser 拡張&lt;/H3&gt;
&lt;P&gt;S3で1MB以上のデータを転送するためには、DIME という仕様を使う必要があります。AmazonのResourceCenterにあるサンプルS3 Bucket BrowserではDIMEを使用してデータのやり取りを行っていないので、今回はそこを拡張しようと思います。 
&lt;P&gt;まず、.NET FrameworkのWebサービスではDIMEを標準ではサポートしていないので、DIME Attachmentを使用するため、WSEをインストールします。ただし、最新のWSEではDIME Attachmentの部分をMTOMという仕様で置き換えてしまっているので、今回はWSE 1.0（注）を使用します。 
&lt;P&gt;注：WSE 2.0を使用してS3にアクセスしようとすると少々問題があるので（WSEの中のWS-Addressingの実装を強制され、サーバ側でエラーが発生する）、WSE 1.0を使用しています。 
&lt;P&gt; 
&lt;H4&gt;WSE 1.0 SP1 インストール&lt;/H4&gt;
&lt;P&gt;&lt;A href="http://www.microsoft.com/downloads/details.aspx?familyid=06255a94-2635-4d29-a90c-28b282993a41&amp;amp;displaylang=en"&gt;WSE 1.0 SP1&lt;/A&gt; をダウンロードし、インストールします。 
&lt;P&gt; 
&lt;H4&gt;WSE 1.0 を参照に加える&lt;/H4&gt;
&lt;P&gt;Microsoft.Web.Serviceを参照に加えます。 
&lt;P&gt; 
&lt;H4&gt;コードの変更&lt;/H4&gt;
&lt;H4&gt;Webサービスプロキシの親クラスをMicrosoft.Web.Services.WebServicesClientProtocolに変更&lt;/H4&gt;
&lt;P&gt;まず、Visual Studioの[ソリューションエクスプローラ]で[すべてのファイルを表示]するようにします。 
&lt;P&gt;そうすると、[Web References]のcom.amazonaws.s3を展開できるようになるので、Refence.csというファイルを開きます。これはwsdlで作成されたプロキシクラスです。 
&lt;P&gt;このReference.csの中にあるプロキシクラスの親クラスをSystem.Web.Services.Protocols.SoapHttpClientProtocolからMicrosoft.Web.Services.WebServicesClientProtocolに変更します。 
&lt;P&gt; 
&lt;P&gt;public partial class AmazonS3 : Microsoft.Web.Services.WebServicesClientProtocol 
&lt;P&gt; 
&lt;P&gt; 
&lt;H4&gt;S3コンストラクタ&lt;/H4&gt;
&lt;P&gt;プロキシクラスの設定を行います。 
&lt;P&gt; 
&lt;P&gt;public S3(string sAccessKeyId, string sSecretKey) 
&lt;P&gt;{ 
&lt;P&gt;m_sAccessKeyId = sAccessKeyId; 
&lt;P&gt;m_sSecretAccessKey = sSecretKey; 
&lt;P&gt;m_objS3.RequestSoapContext.Path.MustUnderstand = false; // WS-Routing は使用しないので、falseにする。 
&lt;P&gt;} 
&lt;P&gt; 
&lt;H4&gt;S3.PutObject(string bucketName, string keyName, string fileName, long contentLength, string contentType)メソッド追加&lt;/H4&gt;
&lt;P&gt;内容はPutObjectInlineからコピってきます。基本的にはPutObjectInlineと一緒ですが、DIME Attachmentにアップロードするファイルを追加しましょう。 
&lt;P&gt; 
&lt;P&gt;m_objS3.RequestSoapContext.Attachments.Add(new Microsoft.Web.Services.Dime.DimeAttachment(contentType, Microsoft.Web.Services.Dime.TypeFormatEnum.MediaType, fileName)); 
&lt;P&gt;objS3PutObjectResult = m_objS3.PutObject(bucketName, keyName, aobjMetaDataEntries, contentLength, null, 0, false, AccessKeyId, timeStamp, true, sSignature, null); 
&lt;P&gt; 
&lt;H4&gt;S3.GetObjectメソッド修正&lt;/H4&gt;
&lt;P&gt;Objectを取得するときは、Webメソッドの引数でDIMEかInlineか選択できます。なので、S3.GetObjectメソッドにbool isOver1MBObjectというObjectのサイズが1MBを超えているかどうか判断できる引数を追加します。Webサービスから取得したDIME AttachmentのStreamはそのままファイルに焼き付けたほうが効率がいいのですが、今回はGetObjectResult.Dataにバイト配列として格納してしまいます。（コードの修正が少なくて済むので&amp;#8230;） 
&lt;P&gt; 
&lt;P&gt;public GetObjectResult GetObject(string bucketName, string keyName, bool isOver1MBObject) 
&lt;P&gt;{ 
&lt;P&gt;（中略） 
&lt;P&gt;try 
&lt;P&gt;{ 
&lt;P&gt;objS3GetObjectResult = m_objS3.GetObject(bucketName, keyName, true, true, !isOver1MBObject, AccessKeyId, timeStamp, true, sSignature, null); 
&lt;P&gt;m_bSoapError = false; 
&lt;P&gt;m_sSoapErrorMessage = ""; 
&lt;P&gt;if (isOver1MBObject) 
&lt;P&gt;{ 
&lt;P&gt;Stream stream = m_objS3.ResponseSoapContext.Attachments[0].Stream; 
&lt;P&gt;byte[] buffer = new byte[(int)stream.Length]; 
&lt;P&gt;stream.Read(buffer, 0, (int)stream.Length); 
&lt;P&gt;objS3GetObjectResult.Data = buffer; 
&lt;P&gt;} 
&lt;P&gt;} 
&lt;P&gt;（中略） 
&lt;P&gt;return objS3GetObjectResult; 
&lt;P&gt;} 
&lt;P&gt; 
&lt;H4&gt;Objectのサイズの取得&lt;/H4&gt;
&lt;P&gt;ファイルをアップロードしようとする場合はFileInfoなどで確認すれば良いのですが、ファイルをダウンロードしようとする場合は、listView1.Items[n].SubItems[3]から取得します。 
&lt;P&gt; 
&lt;H4&gt;コンパイルと実行&lt;/H4&gt;
&lt;P&gt;細々とした部分は省略しましたが、後はコンパイルして実行すれば1MB以上のデータをやりとりできるようになります。ちなみに、1MB以上のデータを画面右にドロップすると数秒間固まります（笑）。 
&lt;P&gt; 
&lt;P&gt;今回はWSEを使用してDIME Attachmentを使用してファイルを送受信するようにS3 Bucket Browserを拡張しましたが、Webサービス関連は調べれば調べるほど恐ろしくなってきますね&amp;#8230;まさに伏魔殿って感じです。最近の仕様もWSE関連は複雑化の一途を辿っている様に見えますし、もっと簡単にならないのかな&amp;#8230;日本語のドキュメントももっと作って欲しいなーなんて思ってますｗ 
&lt;P&gt; 
&lt;P&gt;# WSE 2.0 を使った場合についてですが、実は自分を中継サーバと勘違いさせ（m_objS3.Pipeline.IsIntermediary = true;）、パイプライン処理の最後でWS-Addressing等の情報を削除させることができます。これでいけることはいけるのですが、あまりにも強引な方法なので使わない方が良いと思います。それよりも、「Discussions in Web Services Enhancements」というマイクロソフトのニュースグループでWS-Addressingを無効にする話題に上っていて、パイプライン処理にカスタムクラスを差し込めばなんとかなりそうなことが書かれていました。ちょっとメールで問い合わせ中です。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/65352.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>