連載:ADO.NET Entity Framework入門

第7回 EF4によるN層アーキテクチャと自己追跡エンティティ【後編】

WINGSプロジェクト 土井 毅 著/山田 祥寛 監修
2011/01/07
Page1 Page2 Page3

■Silverlightアプリケーションの実装 − UI実装とWCFサービス呼び出し

 AddressBookSilverlightAppプロジェクトのMainPage.xamlファイルを開き、<Grid>要素以下のXAMLコードをリスト2のように修正しよう。

<sdk:DataGrid AutoGenerateColumns="False" Height="237"
     HorizontalAlignment="Left" Margin="8,12,0,0" Name="dataGrid1"
     VerticalAlignment="Top" Width="376" ItemsSource="{Binding}"
     Grid.Column="1">
  <sdk:DataGrid.Columns>

    <sdk:DataGridTextColumn
        Binding="{Binding Path=Name}" Header="Name" />

    <sdk:DataGridTextColumn
        Binding="{Binding Path=TelNo}" Header="TelNo" />

    <sdk:DataGridTextColumn
        Binding="{Binding Path=MailAddress}" Header="MailAddress" />

    <sdk:DataGridTextColumn
        Binding="{Binding Path=Age}" Header="Age" />

  </sdk:DataGrid.Columns>
</sdk:DataGrid>

<Button Content="Load" Height="23" HorizontalAlignment="Left"
  Margin="59,265,0,0" Name="loadButton" VerticalAlignment="Top"
  Width="75" Click="loadButton_Click" Grid.Column="1" />

<Button Content="Save" Height="23" HorizontalAlignment="Left"
  Margin="152,265,0,0" Name="saveButton" VerticalAlignment="Top"
  Width="75" Click="saveButton_Click" Grid.Column="1" />
リスト2 アプリケーションのXAMLコード(C#/VB共通)

 このXAMLコードで、図9のようにデータ表示/編集用のDataGridコントロールと、データ取得/保存用のButtonコントロールが配置される。

 DataGridコントロールの各列には、取得したEntryクラスのName/TelNo/MailAddress/Ageプロパティが一覧表示されるように定義されている。なお、DataGridコントロールは標準で編集機能にも対応しており、データをダブルクリックすることで、その場で値の入力が可能な便利なコントロールである。


図9 DataGridコントロールとButtonコントロールの配置

 続いてコードビハインド・コード(MainPage.xaml.cs/MainPage.xaml.vb)を開き、リスト3のようにコードを入力する。

// WCFサービス呼び出し用のプロキシ・クラス
AddressBookServiceReference.AddressBookServiceClient service;

// UIロード時のイベント・ハンドラ
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
  // プロキシ・クラスを生成
  service =
    new AddressBookServiceReference.AddressBookServiceClient();
}

// Loadボタンクリック時のイベント・ハンドラ
private void loadButton_Click(object sender, RoutedEventArgs e)
{
  // GetEntriesメソッド呼び出し。Silverlightなので非同期呼び出し
  service.GetEntriesCompleted+= new EventHandler<AddressBookServiceReference.GetEntriesCompletedEventArgs>(service_GetEntriesCompleted);
  service.GetEntriesAsync();
}

// GetEntries呼び出し完了イベントのハンドラ
void service_GetEntriesCompleted(object sender, AddressBookServiceReference.GetEntriesCompletedEventArgs e)
{
  // DataGridコントロールに取得してきた
  // Entryクラス一覧をデータバインド
  dataGrid1.ItemsSource = e.Result;
}

// Saveボタン・クリック時のイベント・ハンドラ
private void saveButton_Click(object sender, RoutedEventArgs e)
{
  // DataGridにデータバインドされたEntryクラス一覧を取得
  var entries = dataGrid1.ItemsSource.Cast<Entry>();

  // UpdateEntriesメソッド呼び出し。Silverlightなので非同期呼び出し
  service.UpdateEntriesCompleted
    += new EventHandler<UpdateEntriesCompletedEventArgs>
                            (service_UpdateEntriesCompleted);
  service.UpdateEntriesAsync(
                    new ObservableCollection<Entry>(entries));
}

// UpdateEntries呼び出し完了イベントのハンドラ
void service_UpdateEntriesCompleted(object sender, UpdateEntriesCompletedEventArgs e)
{
  // メソッド呼び出し結果を表示
  MessageBox.Show("データ保存" + (e.Result ? "成功" : "失敗"));
}
' WCFサービス呼び出し用のプロキシ・クラス
Dim service As AddressBookServiceReference.AddressBookServiceClient

' UIロード時のイベント・ハンドラ
Private Sub UserControl_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
  ' プロキシ・クラスを生成
  service = New AddressBookServiceReference.AddressBookServiceClient()
End Sub

' Loadボタン・クリック時のイベント・ハンドラ
Private Sub loadButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

  ' GetEntriesメソッド呼び出し。Silverlightなので非同期呼び出し
  AddHandler service.GetEntriesCompleted, _
                        AddressOf service_GetEntriesCompleted
  service.GetEntriesAsync()

End Sub

' GetEntries呼び出し完了イベントのハンドラ
Private Sub service_GetEntriesCompleted(ByVal sender As Object, ByVal e As AddressBookServiceReference.GetEntriesCompletedEventArgs)

  ' DataGridコントロールに取得してきたEntryクラス一覧をデータバインド
  dataGrid1.ItemsSource = e.Result

End Sub

' Saveボタンクリック時のイベント・ハンドラ
Private Sub saveButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

  ' DataGridにデータバインドされたEntryクラス一覧を取得
  Dim entries = dataGrid1.ItemsSource.Cast(Of Entry)()

  ' UpdateEntriesメソッド呼び出し。Silverlightなので非同期呼び出し
  AddHandler service.UpdateEntriesCompleted, _
                    AddressOf service_UpdateEntriesCompleted
  service.UpdateEntriesAsync(_
                    New ObservableCollection(Of Entry)(entries))

End Sub

' UpdateEntries呼び出し完了イベントのハンドラ
Private Sub service_UpdateEntriesCompleted(ByVal sender As Object, ByVal e As UpdateEntriesCompletedEventArgs)

  ' メソッド呼び出し結果を表示
  If e.Result Then
    MessageBox.Show("データ保存成功")
  Else
    MessageBox.Show("データ保存失敗")
  End If

End Sub
リスト3 WCFサービスの実装

 ここでは、

  • :プロキシ・クラスの生成
  • :Loadボタンをクリックした場合のGetEntriesメソッドの呼び出し
  • :Saveボタンをクリックした場合のUpdateEntriesメソッドの呼び出し

を行っている。

 先にも述べたとおり、WCFサービスを呼び出すためには、サービス参照の追加の際に生成されたプロキシ・クラスを用いる必要がある。 でプロキシ・クラスをフィールドとして定義し、 のUIロード時にインスタンスを生成する。

 Loadボタンをクリックした場合( )には、GetEntriesメソッドを呼び出してエントリ一覧を取得している。ここで注目したいのは、単純にプロキシ・クラスのGetEntriesメソッドを呼び出すのではなく、非同期呼び出しを行っている点である。これは、SilverlightからWCFを呼び出す場合に、非同期操作のみがサポートされているためである。

 ここではGetEntriesメソッドの呼び出しが完了した場合に呼び出されるGetEntriesCompletedイベントのハンドラを登録し、その後GetEntriesAsyncメソッドでGetEntriesメソッドの呼び出しを開始している。

 GetEntriesメソッドの呼び出し完了後に呼び出されるservice_GetEntriesCompletedメソッドでは、取得したエントリ一覧をDataGridコントロールへデータバインドしている。

 Saveボタンをクリックした場合( )は、DataGridコントロールにバインドされたデータを取り出し、UpdateEntriesメソッドを先ほどと同様に非同期呼び出ししている。非同期呼び出し後は、サーバサイドでのデータベース更新が成功したかどうかをダイアログで表示する。

■サンプルの実行

 それではAddressBookSilverlightApp.Webプロジェクトをスタートアップ・プロジェクトに設定して実行してみよう。

 なお、SilverlightのプロジェクトであるAddressBookSilverlightAppをスタートアップ・プロジェクトにして実行しても、AddressBookSilverlightApp.Webプロジェクトが実行されず、WCFサービスが公開されないため、正しく動作しない。

 サンプルを実行すると、図10のように空のDataGridコントロールが表示される。


図10 Silverlightアプリケーション起動直後

 [Load]ボタンを押してWCFサービス経由でエンティティを表示してみよう。非同期にGetEntriesメソッドが呼び出され、DataGridコントロールにデータが表示される(図11)。


図11 自己追跡エンティティを取得して表示
[Load]ボタンを押すと、WCFサービスを介して自己追跡エンティティを取得し、DataGridコントロールにデータが表示される。

 DataGridコントロールの任意のセルをダブルクリックするか、[F2]キーを押すことで、そのセルのデータを編集できる。編集後は[Save]ボタンを押すと、非同期にUpdateEntriesメソッドが呼び出され、データ更新結果がダイアログ表示される(図12)。前述のとおり、自己追跡エンティティがクライアントサイドでのデータの変更履歴を保持し、その変更履歴を元にサーバサイドでデータベースへの更新処理が行われている。


図12 データを編集後、Saveボタンを押してWCFサービスを介してデータを保存

 以上、Entity FrameworkをN層アーキテクチャに用いるサンプルを構築することで、自己追跡エンティティの効用を理解することができた。特に、.NET Frameworkのサブセット的な位置付けであるSilverlightにおいても、自己追跡エンティティをまったく変更なしに使用できるのは大きなメリットである。

まとめ

 全7回となったEntity Framework入門では、Entity Frameworkの理念から実際の活用方法まで解説した。昨今のデータベース業界はKey-Valueストア*1と呼ばれる、非リレーショナルなデータベース・モデルが人気を博しているが、業務システム構築においては依然としてリレーショナル・データベースの存在は大きい。Entity Frameworkのようなリレーショナル・データベースとオブジェクト指向言語の間を取り持つソフトウェアは今後も重要な役割を果たしていくだろう。

*1 1つのKey(=ID)に対して1つのValue(=値)を保存する機能だけを持つ、シンプルなデータベース。GoogleのBigtable、Amazon SimpleDB、MicrosoftのAzure Storage Servicesなどがある。

 また、第5回で解説した「コード・ファースト」開発は、良い意味で.NETらしくない、より迅速な開発スタイルを切り開いてくれる、今後も注目していきたいスタイルだ。

 まだ新しい技術であるEntity Frameworkだが、本連載が活用の手助けとなることを願って結びとしたい。End of Article

 

 INDEX
  ADO.NET Entity Framework入門
  第7回 EF4によるN層アーキテクチャと自己追跡エンティティ【後編】
    1.WCFによるサービスの公開/プロジェクトの追加/WCFサービスの実装
    2.Silverlightアプリケーションの実装 − サービス参照の追加
  3.UI実装とWCFサービス呼び出し/サンプルの実行/まとめ
 
インデックス・ページヘ  「ADO.NET Entity Framework入門」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間