ストアドプロシージャの実行
ストアドプロシージャに関してはさまざまな議論がありますが、実際問題として業務のアプリケーションで使用しているケースは多いはずです。そこでSilverlightを使用して、データベースが持つストアドプロシージャを実行する方法を紹介したいと思います。
これにはいくつかの手法が考えられるのですが、Silverlightでデータベースを使用するためには、バックエンドでADO.NET Entity Frameworkを使用することがほとんどのため、ADO.NET Entity Frameworkを利用した呼び出しを行う方法が設計上で一番シンプルです。また、呼び出しロジックを外部に公開するためには、WCFでサービスを構築する形がよいでしょう。以下にサンプルシステムでの手順を紹介します。
手順
- MSStoreSample.ModelsのプロジェクトのMSStoreSample.edmxをダブルクリックしてEDMのデザイナーを表示すると[モデルブラウザ]が表示されます。
- [MSStoreSampleModel.Store]の下の[ストアドプロシージャ]から、sp_CreateOrderを右クリックして、[関数インポートの作成]メニューを選択します。
- [関数インポートの追加]画面の、[関数インポート名]を「CreateOrder」、[戻り値の型]を[なし]にして[OK]ボタンを押下します。
- モデルブラウザ内にCreateOrderが作成されているのを確認します。
- Web側のプロジェクトに[新しい項目]として[Silverlight対応のWCFサービス]を選択してWCFサービスを追加します(名前をOrderService.svcとします)。
- 作成されたOrderService.svcのコード(OrderService.svc.cs)を開いて、OrderServiceクラスに以下のOperationContract(CreateOrderオペレーション)を作成します。ここでは、インポートされたCreateOrderのストアドプロシージャを呼び出して注文を作成します。
[OperationContract] public void CreateOrder(string userId, int paymentType, Guid creaditCardId) { using (MSStoreSampleEntities context = new MSStoreSampleEntities()) { context.Connection.Open(); using (DbTransaction transaction = context.Connection.BeginTransaction()) { // 注文を作成します using (DbCommand command = context.Connection.CreateCommand()) { command.CommandType = CommandType.StoredProcedure; command.CommandText = "MSStoreSampleEntities.CreateOrder"; command.Parameters.Add( new EntityParameter("UserId", DbType.String) { Value = userId }); command.Parameters.Add( new EntityParameter("PaymentType", DbType.Int32) { Value = paymentType }); command.Parameters.Add( new EntityParameter("CreditCardId", DbType.Guid) { Value = creaditCardId }); command.Parameters.Add( new EntityParameter("ReturnValue", DbType.Int32) { Direction = ParameterDirection.ReturnValue }); command.ExecuteNonQuery(); } } } }
このコードは、一見通常のADO.NETを使用しているようにも見えますが、実際はEntity Client(ADO.NET Entity Framework用のデータプロバイダと考えてください)を使用してストアドプロシージャ呼び出しを行っています。なお、Visual Studio 2010(.NET Frame work 4)を用いる場合、ADO.NET Entity Frameworkのバージョンが上がり、Entity Clientのみではなく、さらに上のレイヤーであるObject Services用のコードもジェネレートされるため、下記のような簡単な実装も可能になります。
[OperationContract] public void CreateOrder(string userId, int paymentType, Guid creaditCardId) { using (MSStoreSampleEntities context = new MSStoreSampleEntities()) { context.CreateOrder(userId, paymentType, creaditCardId); } }
これでサービス側の作成は完了です。
クライアント側の処理は非常に単純です。サービスの参照を追加して、OrderServiceをクライアント側で使用する形にします。その状況で下記のようなコードの実装をすることで、ストアドプロシージャ呼び出しを行うことが可能です。
private void paymentButton_Click(object sender, System.Windows.RoutedEventArgs e) { OrderServiceClient client = new OrderServiceClient(); client.CreateOrderCompleted += CreateOrderCompleted; client.CreateOrderAsync(AuthenticationContext.Current.User.UserName, 3, Guid.Empty); } void CreateOrderCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { if (e.Error != null) throw e.Error; }
ただし注意しなければならないのは、ここでも非同期の処理になる点です。公開されているのはCreateOrderメソッドですが、Silverlightから呼び出す場合、CreateOrderAsyncという形で非同期の処理になっていることが分かると思います。
なお、サンプルシステムで実行すると下図のように購入処理が完了し、履歴が表示されるようになっています。
まとめ
今回の連載では、Silverlightにおけるデータ処理のほんの入り口を紹介させていただきました。ほかにも、今回は省略してしまいましたが、サーバ側の処理の中にトランザクションをかけること、データ処理の前に必要な認証の処理、同時実行の制御、エラーのハンドリング、画面の遷移など、実開発の局面では考慮しなければならないポイントが多数あります。サンプルシステムの中でもある程度触れているので、本連載と併せて学習のきっかけとなれば幸いです。
また、Silverlight 4では、Visual Studio 2010を用いることによって、かなり効率の良い開発環境を手にできます(GUIで画面構築ができる点などは、その端的な機能の1つです)。そうした状況からも、Silverlightはもはや特別な開発プラットフォームではなくなってきているのかもしれません。ぜひ、今後はそうした視点も持ってSilverlightをチェックしてみてください。