かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

WCF RIA Servicesで更新の処理を書いてみた

WCF RIA Servicesで更新ってどうやるのか見てみました。
基本的には、Silverlight側で変更箇所を記録しておいて、DomainContextのSubmitChangesメソッドで一括でサーバに送るといった寸法みたいです。
早速やってみました。

足場づくり

RIAUpdateという名前でSilverlight アプリケーションを作成します。そしてRIAUpdate.WebプロジェクトにPeopleServiceという名前でDomainServiceを作成します。
とりあえず、適当に100件の人のデータを返すようにGetPeopleメソッドを実装します。


namespace RIAUpdate.Web
{
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.ServiceModel.DomainServices.Hosting;
    using System.ServiceModel.DomainServices.Server;


    [EnableClientAccess()]
    public class PeopleService : DomainService
    {
        /// <summary>
        /// 適当な人のデータをとりあえず100件返す
        /// </summary>
        /// <returns>人のデータ</returns>
        public IQueryable<Person> GetPeople()
        {
            return Enumerable.Range(1, 100).Select(
                i => new Person
                {
                    ID = i,
                    Name = "田中 太郎" + i,
                    Age = 20 + i % 10
                }).AsQueryable();
        }
    }

    /// <summary>
    /// 人
    /// </summary>
    public class Person
    {
        [Key]
        public int ID { get; set; }

        public string Name { get; set; }

        public int Age { get; set; }
    }
}

この状態でプロジェクトをビルドしてSilverlightプロジェクト側にコードを生成します。次に、MainPage.xamlを開いてデータソースからPersonをドラッグアンドドロップします。

ドロップするとDataGridが作成されます。(微妙に位置調整とマージンの調整をしています)

これで実行すると、DataGridにPersonのデータが100件表示されます。

更新処理を作ってみよう

現状でDataGridのデータを編集しようと思うと、更新はサポートされていないと以下のようなエラーが表示されてしまいます。

これは、サーバーサイドに更新用メソッドが作成されていないためにおきます。更新用のメソッドは、void UpdatePerson(Person p)というメソッドを用意すれば更新が有効になります。
普通は個々でDBにデータを格納したりするのですが、ここではログを出すように実装しました。

/// <summary>
/// 更新処理。ログだけ出す
/// </summary>
/// <param name="p">更新対象</param>
public void UpdatePerson(Person p)
{
    // GetOriginalで変更前を取得可能
    var org = base.ChangeSet.GetOriginal(p);
    Debug.WriteLine("変更前 ID={0}, Name={1}, Age={2}", org.ID, org.Name, org.Age);
    Debug.WriteLine("変更後 ID={0}, Name={1}, Age={2}", p.ID, p.Name, p.Age);
}

そして、MainPageから更新結果をサーバに転送するためのトリガーとなるボタンを用意します。このボタンは、画面に作成されているDomainDataSourceのSubmitChangesCommandとバインドします。
こうすることで、更新が可能な状態になったら自動的にボタンが押せるようになったり、ボタンを押すことでDomainContextのSubmitChangesが呼ばれるようになります。

<Button 
  Name="button1" 
  Content="Submit" 
  Height="23" 
  HorizontalAlignment="Left" 
  Margin="13,12,0,0" 
  VerticalAlignment="Top" 
  Width="75" 
  Command="{Binding ElementName=personDomainDataSource, Path=SubmitChangesCommand}" />

一番したのCommandプロパティの設定がポイントになります。

ここまで出来たら実行して動きを確認します。
実行直後なので、まだSubmitボタンは押せない。

適当に編集をするとSubmitボタンが押せるようになる。

ボタンを押すと以下のような結果がデバッグの出力に出てきます。

変更前 ID=1, Name=, Age=0
変更後 ID=1, Name=ア太郎, Age=21
変更前 ID=2, Name=, Age=0
変更後 ID=2, Name=イ太郎, Age=22

どうも、ChangeSet.GetOriginalでは、このつくりだとちゃんとオリジナルの値は取れないみたいです。要研究。

以上がWCF RIA Servicesの更新処理の簡単な動きでした。