WCF RIA Services プロジェクトのWindows Azure への配置上の注意点とAzure Table Storageの利用例

皆様、こんにちは!

だいぶご無沙汰してしまいまして申し訳ございません。先日のPDC Japan 10でのHTML5のセッションは、大変高いご評価を戴いたようで誠に有難うございます。今後も良いセッションをご提供できるよう、また最新かつ有益な情報を皆様にご提供できるよう努めていきたいと思います。今後ともよろしくお願いいたします。

さて本日は、久々にWCF RIA Services ネタをご紹介しておきますね。

これ本当は、夏のTech・Edのセッションでご紹介するつもりだったのですが、シナリオ上、Azure連携まで行いますと、時間が足りないため、泣く泣く?省略したものになります(まあ、元々かなりのボリュームでしたので仕方ないのですが(^^;)ゞ)

1.WCF RIA Services プロジェクトのWindows Azure への配置上の注意点

この点は、先日のMVP Open Dayでもご質問を戴いたのですが、意外に知られていないので、共有することにしました。まずはこちらをご参照くださいませ。

前提としては、以下の通りです。

Windows Azure SDK 1.2 以降(.NET 4 対応) がインストールされていることが前提

1.3でももちろんOKです。

手順としては、例えば、

Intellitrace をオフにする

・空の Azure プロジェクトを追加

・Web Role にサーバー側プロジェクトを追加

System.ServiceModel.DomainServices.*.dll 3つの Local Copy = True に設定

・Cloud プロジェクトの発行 (デプロイ)

という手順になります。
この手順で下記プロダクトが動作します。特にアンダーラインを引いた2つが重要ですので、ご注意下さい。

Silverlight 4, WCF RIA Services, Windows Azure、SQL Azure, Entity Framework 4

ぜひ、お試しください。

2.Azure Table Storageの利用例

続いて、WCF RIA Services 1.0 SP1のToolkitで追加されたAzure Tableの取り扱いについて、ご紹介します。あくまでも一利用例でかつさわりですので、今後、また加筆修正していきます。

(1) RIA Services SP1 December Toolkit Release

まず、このサポートは、WCF RIA Services SP1 Beta releaseに伴うRIA Services December Toolkit releaseに含まれていることにご注意ください。WCF RIA Services SP1本体ではありません。
以前も、WCF RIA Services から Table Storage を操作することは可能だったのですが、今回は、可及的にシンプルにそれを可能にしました。PDC10にて発表された Azure の新しい特徴を活かしつつ、 WCF RIA Services からの Table Storage 利用を最適化した、といってよいでしょう。

(2) どこからスタートするか?

まずそもそもWindows Azure が初めての場合、Jim Nakashima’s blog を一読するのがお薦めです。
その他の話題でも、大変有益なエントリが多く継続して購読したいブログですよね。Table storage のはじめの一歩としては、こちらのエントリが最適だと思います。
Jim のアプローチとここで紹介するアプローチの違いは、既存のDomainService パターンと統合するためのステップです。
以下では、Microsoft.ServiceModel.DomainServices.WindowsAzure アセンブリのプレビューを利用した解説を行います。

(3) プロジェクトのセットアップ

まずは、空の Silverlight プロジェクトを生成し、Azureで使えるようにしてお来ます。もし、Business Application Template を使いたければ、こちらのエントリを参照してください。
1) 最新の Windows Azure SDK がインストール済みであることを確認(https://www.microsoft.com/windowsazure/)
2) Visual Studio を起動し、新しい Silverlight プロジェクトを生成し、“WCF RIA Services を有効にする”にチェック
3) Windows Azure Cloud Service プロジェクトをこのソリューションに追加
“新しいクラウドサービス”の追加ウィザードが立ち上がったらOKクリック
4) Cloud Service プロジェクトのソリューションエクスプローラの中で、Roles を右クリックし、Web ロールをこのソリューション内から追加する

image

5)Web Role をこのソリューション内から選択するウィザードの中で、Silverlight の Web Application プロジェクトを選択

image

6) 次に、RIA Services の参照をWeb Application プロジェクトに追加
(やり方として色々ありますが、ここでは、空の DomainService をウィザードを使用して追加し、それをすぐに削除するというやり方を紹介します)

image

7) このアプリケーション を Azure にデプロイできるように、System.ServiceModel.DomainServices.Hosting のプロパティから、Local Copy = True に設定

image

Web プロジェクトの中で、下記の両 .dll が更新されることを確認
System.ServiceModel.DomainServices.Hosting
System.ServiceModel.DomainServices.Server

8) これで準備は完了したので、Windows Azureで動かすための参照を、Web Application プロジェクトに追加
System.Data.Services.Client
Microsoft.WindowsAzure.ServiceRuntime
Microsoft.WindowsAzure.StorageClient
Microsoft.ServiceModel.DomainServices.WindowsAzure

下記の両 .dll のCopy Local=True に設定
Microsoft.WindowsAzure.StorageClient
Microsoft.ServiceModel.DomainServices.WindowsAzure

4) Windows Azure Entity

プロジェクトのセットアップは完了したので、次にWindows Azure Table Storage の利用法に移ります。
Azure Table Storage はクエリー問い合わせ可能な構造化ストレージであり、テーブルの作成は無制限です。その代り、無制限のエンティティが出現しますので、そこで、その構造に対していくつか主キーを作る必要あります。ただ、それは柔軟に可能です (詳細については Table Storage whitepaperを参照のこと)

皆様ご存じの通り、唯一の非常に厳しいルールとして、全てのエンティティは、3つのプロパティを持つこと - PartitionKey、RowKey、Timestamp - があります。
これらにより、各エンティティにユニークなキーを作成できます。更に、クエリーの結果は PartitionKey で第一次的にソートされ、次に RowKey でソートされることになります。

Table Storage を使う最初のステップはエンティティの定義です。エンティティの定義を簡単にするベースクラス  - TableEntity があります。PartitionKey、RowKey、Timestamp の3つのプロパティを持ちます。これはこれをスクラッチで作成し、エンティティの持つプロパティで、Table Storage のスキーマを定義します。

 public class MyEntity : TableEntity 
{ 
    public string MyName { get; set; }
 }

このコードの中では、エンティティと4つのプロパティ :  PartitionKey、RowKey、Timestamp、MyName を定義しています。

エンティティが作成できたら、この Table Storage を WCF RIA Services から利用するための データコンテキスト を定義します。

5) Table Storage 用データコンテキスト

これは、Azure Table Storage との連携の2番目のステップとなります。まずは DomainService を使えるようコンテキストを生成します。

RIA Services で使うため提供された2つのタイプは下記の通りです。

TableEntitySet TableEntityContext

 public class MyEntityContext : TableEntityContext 
{ 
    public MyEntityContext() : 
  base(RoleEnvironment.GetConfigurationSettingValue("DataConnectionString")) 
    { 
    } 

    public TableEntitySet<MyEntity> MyEntities 
    { 
  get { return base.GetEntitySet<MyEntity>(); } 
    }
 }

次に、Web Role Configurationで設定されたconnection stringを参照し、Web Role プロパティを開いて新たな connection stringを追加します。

image

このように、僅かなコードの追加で DomainServices を追加可能です。

6) Table Storage Domain Service

エンティティを定義しコンテキストを準備してから、 DomainService を生成することになります。

この場合に利用するベースクラスが TableDomainService というものです。これは、テーブルストレージ固有の処理が可能となっています。すなわち、これを利用することにより、ビジネスロジックの作成に集中できるという訳です。

  [EnableClientAccess]
  public class MyDomainService : TableDomainService<MyEntityContext>
  {
    public IQueryable<MyEntity> GetMyEntities()
    {
      return this.EntityContext.MyEntities;
    }

    public void AddMyEntity(MyEntity entity)
    {
      this.EntityContext.MyEntities.Add(entity);
    }

    public void DeleteMyEntity(MyEntity entity)
    {
      this.EntityContext.MyEntities.Delete(entity);
    }

    public void UpdateMyEntity(MyEntity entity)
    {
      this.EntityContext.MyEntities.Update(entity);
    }
  }

このサンプルでは、シンプルな CRUD 操作を実装 下のみですが、当然、DomainService は更に自由にカスタマイズ可能です。

7) このシナリオにおける利点

一度 DomainService を作成すれば、WCF RIA Servces の利用で慣れ親しんだ全てが利用可能です。

例えば、

・チェンジトラッキング ・バリデーション ・DomainDataSource の利用

これは次項のソースコード参照してください。ドラッグ&ドロップで DomainService を利用する DataGrid を追加できることも大きいでしょう。

 <UserControl … >

    <StackPanel …>
        
          <dds:DomainDataSource 
   ElementName= "myEntitiesDDS" QueryName="GetMyEntitiesQuery">
         <dds:DomainDataSource.DomainContext>
                  <web:MyDomainContext />
           </dds:DomainDataSource.DomainContext>
         </dds:DomainDataSource>
      <sdk:DataGrid ItemsSource=
        "{Binding ElementName=myEntitiesDDS, Path=Data}“ />
    
    </StackPanel>

  </UserControl>

以上です。いかがでしょうか?RDBとEntity Frameworkを使う場合に比べると、手動でやる部分がどうしても多くなるとは思いますが、Tableを使えるので非常に便利です。ぜひお試しください。

なお本エントリへの追加・修正等は適宜行っていく予定です。

鈴木 章太郎