QA@IT

データセットからAPIへの移行方法について

5033 PV

いつもお世話になっています。

データセットを使用してデータベースにアクセスするWindowsフォームアプリがあります。
現状ではアプリケーションが直接データベースに接続しているのですが、セキュリティの観点から、アプリケーションサーバーを経由してデータの取得・更新を行うよう修正しなければならなくなりました。
自分なりに調べては見たのですが、皆様のお知恵をお借りできればと思い、投稿いたしました。

開発環境:
Visual Studio 2012 (VB)
.NET Framework 4.5
SQL Server 2012 Standard

APPサーバー環境:
Windows Server 2003
IIS 6

現状のクライアントアプリではクエリ(GetDataByKey/FillByKey)やDataRow(テーブル名Row)、オプティミスティック同時実行制御など、データセットの機能をふんだんに利用しています。
見当違いかもしれませんが、「動的データエンティティWEBサイト」や、「WCFサービス」等、調べては見ましたが、どの技術を利用するのが適当なのか、私の知識では判断することができませんでした。

目標としては、第一に極力修正の工数を抑えたい、次に、可能ならばデータセットと似た使いかた(なんと表現してよいか悩みますが…)ができればと思っています。

皆様がこのような修正を請け負った場合、どのような技術を利用されるのか、また、お奨めのものがありましたらご教授いただきたく思います。
足りない情報があれば追記いたします。
どうぞよろしくお願いいたします。

回答

Web サービス(.asmx)を利用して、Windows アプリとの間で型付 DataSet をやりとりすることで「第一に極力修正の工数を抑えたい、次に、可能ならばデータセットと似た使いかた」ができそうです。

以下のような感じです。基本的なところは期待通り動くことは一通り確認しましたが、予期しない問題があるかもしれませんし、例外処理など細かいところまでは見てません。なので、あくまで「感じ」ですのでご注意ください。

Web サービスのコードは以下の通りです。ProductsDataSet, ProductsTableAdapter, TableAdapterManager は Visual Studio の「データソース構成ウィザード」を使って自動生成させた .xsd ファイル下の .Designer.cs に含まれる型付 DataSet + TableAdapter + TableAdapterManager です。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

namespace WebApplication1
{
    /// <summary>
    /// ProductsWebService の概要の説明です
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // この Web サービスを、スクリプトから ASP.NET AJAX を使用して呼
    // び出せるようにするには、次の行のコメントを解除します。 
    // [System.Web.Script.Services.ScriptService]
    public class ProductsWebService : System.Web.Services.WebService
    {

        [WebMethod]
        public ProductsDataSet GetDataSet()
        {
            ProductsDataSet dataset = new ProductsDataSet();
            ProductsDataSetTableAdapters.ProductsTableAdapter adapter = 
                new ProductsDataSetTableAdapters.ProductsTableAdapter();

            adapter.Fill(dataset.Products);
            return dataset;
        }

        [WebMethod]
        public int Update(ProductsDataSet dataset)
        {
            ProductsDataSetTableAdapters.ProductsTableAdapter adapter = 
                new ProductsDataSetTableAdapters.ProductsTableAdapter();
            ProductsDataSetTableAdapters.TableAdapterManager manager = 
                new ProductsDataSetTableAdapters.TableAdapterManager();
            manager.ProductsTableAdapter = adapter;
            int n = manager.UpdateAll(dataset);
            return n;
        }
    }
}

上記の Web サービスを Windows Forms アプリでは以下のように利用できます。これも Visual Studio のウィザードを利用して、「データソース」ウィンドウの項目を Form 画面にドラッグ&ドロップして自動生成したコードをほぼそのまま利用しています。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace UpdateUsingWebService
{
    public partial class Form2 : Form
    {
        private ProductsServiceReference.ProductsWebServiceSoapClient client;
        private ProductsServiceReference.ProductsDataSet productsDataSet;

        public Form2()
        {
            InitializeComponent();
            InitializeComponent2();
            this.client = new ProductsServiceReference.ProductsWebServiceSoapClient();
        }

        private void productsBindingNavigatorSaveItem_Click(object sender, EventArgs e)
        {
            this.Validate();
            this.productsBindingSource.EndEdit();

            //this.tableAdapterManager.UpdateAll(this.productsDataSet);

            int n = this.client.Update(this.productsDataSet);
            this.productsDataSet = this.client.GetDataSet();
            this.productsBindingSource.DataSource = this.productsDataSet;
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            // TODO: このコード行はデータを 'productsDataSet.Products' テーブルに読み込
            // みます。必要に応じて移動、または削除をしてください。
            //this.productsTableAdapter.Fill(this.productsDataSet.Products);

            this.productsDataSet = this.client.GetDataSet();
            this.productsBindingSource.DataSource = this.productsDataSet;
        }

        // 以下省略

    }
}
編集 履歴 (0)
  • ご丁寧にコードまでご提示いただき、ありがとうございます。私のほうでも確認してみました。なるほど、いい感じです。おかげさまでずいぶんと短縮した工期を報告できそうです。 -

ASP.NET を利用しての Web アプリケーションを開発したいと言うことですか?

であれば、以下の記事のようなことをしたいのですか?

Microsoft Visual Studio 2005による Web アプリケーション構築技法
7.6 データコンポーネント機能によるデータアクセスコンポーネントの開発
http://www.atmarkit.co.jp/fdotnet/bookpreview/vs2005webapp_07/vs2005webapp_07_01.html

編集 履歴 (0)
  • ご回答ありがとうございます。
    やりたいことを簡単に申しますと、「Windowsアプリケーションのデータベースへのアクセス部分のみWEBサービス化したい」ということになります。
    現在はいただいたURLの記事中の「データコンポーネント」を利用しています。
    自動生成されるメソッドやTableAdapterの排他制御の機能などを利用しているので、データのやり取りだけではすまないのが悩みどころです。。
    -
  • Web サービスを含む Web アプリはステートレスということは認識されているるでしょうか? つまり、型付 DataSet / DataTable + TableAdapter のインスタンスはサーバーには保持されないということです。そのあたりが理解されていると、Web サービスにできること / できないことが分かって、多少悩みが減るのではないでしょうか。 -
  • ありがとうございます。仰ることは概ね認識しております。現在のデータコンポーネントを利用している部分を別の手段、例えばWEBサービス等で置き換える方法がないかと思い、質問させていただきました。やはりロジック部分は自前で実装する他ないのでしょうか… -
  • たぶん、今の Windows アプリは DataGridView + 型付 DataSet + TableAdapter を利用して、複数レコードに対するユーザーの編集結果を一気に DB に書き戻すということをしているのではないかと想像していまが、そうだとすると、現在の形のまま一部を Web サービスに移すというのは無理だと思います。 -
  • 「第一に極力修正の工数を抑えたい、次に、可能ならばデータセットと似た使いかた」にはなりませんが、ASP.NET Web API も候補に加えて検討されてはいかがですか? http://www.asp.net/web-api/overview/creating-web-apis/creating-a-web-api-that-supports-crud-operations -
  • もちろん Windows アプリから呼び出すことは可能です。 http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client -
  • 思いつきで検証などはしていませんが、Windows アプリと Web サービス間で型付 DataSet の受け渡しができれば、「第一に極力修正の工数を抑えたい、次に、可能ならばデータセットと似た使いかた」に近いことができるかもしれません。それも検討されてはいかがでしょうか。自分も興味があるので、後で時間ができたらやってみます。 -
  • ありがとうございます。お手数をおかけして申し訳ありません。型付DataSetの受け渡しができれば、かなりの工数を抑えることができそうです!
    TableAdapterのメソッドに関しては、WEBサービスとして自前で実装する他ないような気がしています。
    引き続き調査してまいります。
    -
  • 先に「後で時間ができたらやってみます」と書きましたが、実際に試してみました。詳しくは解答欄を見てください。 -

.NETの場合は結構DataSetはサポートされてたりしますので、将来的なことを考えなければ手段はいろいろあります。
どれを使うか、というところですね。
asmxでも.NET RemotingでもWCFでも使えます。
#最近のREST系のは合わないですね。

編集 履歴 (1)
  • もっとも、いろんなことをきちんと考え出すとそれなりに悩みどころは出てきたりします。
    あと、現行のアプリのつくりによって、大変さは結構変わります。
    UIとビジネスロジックをきちんと分離した造りなら、比較的容易に実現できる可能性もありますが。
    -
  • ご回答ありがとうございます。単純にデータのやり取りだけであれば、こんなに悩むことはなかったのですが、TableAdapterや排他制御など、DataSetドップリな造りになってしまっているのが痛いところです(汗)
    ここでご提案いただいた技術を精査し、方向性を決めたいと思います。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。