意外と簡単!? .NETでOracle「GrapeCity コンポーネント活用 InputMan編」

日本オラクル クロスインダストリー統括本部
OracleDirect テクニカルサービスグループ
大田 浩


目次
はじめに
InputManとは
サンプルアプリケーションのインストール
InputManからODP.NETの利用



 はじめに

 「GrapeCity コンポーネント活用」シリーズは、Microsoft Visual Studio.NETとVBユーザーや.NETユーザーから高い支持を受けているグレープシティ社のコンポーネント製品を組み合わせたOracle対応アプリケーションの開発方法について説明します。
 実際のサンプルアプリケーションを提供することにより、単なるコーディングTipsにとどまらず、より実践的なアプリケーション開発の資料として構成するようにしております。今回はInputMan編ということで、グレープシティ社が提供しているInputManとOracleが提供している.NETからOracleデータベースへネイティブに接続するためのミドルウェアである「Oracle Data Provider for .NET(以下、ODP.NET)を利用したアプリケーションの開発方法について、実際のサンプルアプリケーションを動かしながら確認することができます。今回のサンプルアプリケーションの説明はポイントとなる部分のみの説明になりますので予めご了承ください。
 「意外と簡単!? .NETでOracle」シリーズが.NET開発者でオラクルを利用したい方のシステム構築の一助になれば幸いです。

  「GrapeCity コンポーネント活用」シリーズは以下の4つの構成を予定しています。
  1. ActiveReports編
  2. InputMan編(本書)
  3. Spread編
  4. FlexGrid編
  「GrapeCityコンポーネント活用」シリーズの「InputMan編」は、以下の3つの内容から構成しております。
  1. InputManとは
  2. サンプルアプリケーションのインストール
  3. InputManからODP.NETの利用
  「GrapeCity コンポーネント活用」シリーズにおける開発環境

データベース・サーバー
OS:Microsoft Windows 2000 Professional + SP4
RDBMS:Oracle Database 10g Release 2 Standard Edition for Windows
開発クライアント
OS:Microsoft Windows 2000 Professional + SP4
開発ツール:Microsoft Visual Studio .NET 2003



 InputManとは

 InputManはテキスト、日付・時刻、数値、マスク、コンボなどの目的に合わせて最適化された入力インタフェースコントロールのセットです。XPテーマとOfficeライクなアクティブフラットの2つのスタイルにより、洗練された外観を簡単に実現できます。これらのコントロールに搭載された機能の多くは、プロパティを設定するだけで実現できるため、コーディング量と開発工数を大幅に削減します。エンドユーザーが感じる迷いや陥りやすい誤りを未然に防ぐ設計のInputMan for .NETは、自然でスムーズな入力を可能にし、アプリケーションの基本となる入力インタフェースの構築を強力に支援します。

 InputManのより詳細な情報はグレープシティ社の以下のURLを参照してください。

 グレープシティ社 − InputMan製品情報
 http://www.grapecity.com/japan/support/database/P7_307.htm

 今回はInputManの2006年1月時点で最新版のバージョンである、「InputMan for .NET 3.0J」を使用しております。


 サンプルアプリケーションのインストール

 サンプルアプリケーションは以下のサイトよりダウンロードできます。

 http://otndnld.oracle.co.jp/easy/dotnet/inputman/sample.zip

 ダウンロードファイル(sample.zip)を任意の一時フォルダに保存し、解凍してください。解凍しますと「InputManDemo」、「Config」という2つのフォルダが作成されます。それぞれのフォルダには以下の情報が格納されています。

- InputManDemo
VB.NETで作成されたWindowsアプリケーションが格納されています。

- Config
サンプルアプリケーションで使用するテーブルなどの自動作成スクリプトが格納されています。

 サンプルアプリケーションを実行させるためには、まずOracleデータベース側に今回使用するサンプルスキーマの設定をおこないます。sample.zipを解凍すると作成される「Config」フォルダ内の「gen_inputman.sql」をSQL*PLUSから実行します。今回のサンプルでは画像データをOracleデータベースに格納し、InputManのコントロールで表示しています。このため、その画像をOracleデータベースに読み込む必要があるので、「Config」フォルダ内の「Images」フォルダに格納されている画像ファイル(gifファイル)を「c:¥Temp」フォルダにコピーしてください。「gen_inputman.sql」は「C:¥Temp」フォルダにコピーされた画像ファイルをOracleデータベースに取り込みます。



 画像ファイルをコピーしたら、「Config」フォルダ内の「gen_inputman.sql」をSQL*PLUSなどから以下のように実行してください。このSQLスクリプトの実行は、リモート実行ではなく、ターゲットのデータベースサーバーで実行します。 実行する際に、ユーザー名/パスワードを求められますので、その際にはSYSTEMユーザーとそのパスワードを入力してください。

C:¥>sqlplus /nolog

SQL*Plus: Release 10.2.0.1.0 - Production on 火 2月 14 09:12:05 2006

Copyright (c) 1982, 2005, Oracle. All rights reserved.

SQL> @gen_inputman
*---------------------------------------*
* please enter password of system        *
*---------------------------------------*
Enter password:
接続されました。

ユーザーが作成されました。

権限付与が成功しました。

-<省略> -

PL/SQLプロシージャが正常に完了しました。

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining optionsとの接続が切断されました。


  サンプルアプリケーションの動作確認

 サンプルアプリケーションを実行させるためのOracleのデータベース・オブジェクトを作成したら、次にサンプルアプリケーションの動作確認をおこなってみましょう。ダウンロードファイル(sample.zip)を解凍後に作成されるInputManDemoディレクトリ下にある、VS.NETのソリューションファイル「InputManDemo.sln」をVS.NETから開いてください。InputManDemo.slnファイルには「InputManDemo」プロジェクトが含まれているのが、ソリューション・エクスプローラから確認できます。



 今回のサンプルアプリケーションを実行するには、ODP.NETがインストールされ、VS.NETから参照設定が適切におこなわれている必要があります。ODP.NETのインストール方法などは、「意外と簡単!? .NETでオラクル」スマートクライアント編の「Oracle Data Provider for .NETのインストール」を参照してください。ODP.NETをVS.NETから利用するための準備が整いましたら次にODP.NETからOracleデータベースに接続するための接続文字列を変更します。InputManDemoプロジェクト内にある、Form1.vbのデザイン画面を開き、「empOracleConnection1」コントロールと「departmentOracleConnection1」コントロールの「ConnectionString」プロパティを変更してください。



 初期状態では以下のように設定されています。

User Id=inputman;Data Source=ORCL10GR2;Password=oracle;


 「User Id」では「inputman」と指定していますが、こちらは先ほど説明した「Config」フォルダ内の「gen_inputman.sql」を実行していれば、「inputman」ユーザーが作成されています。「Data Source」はOracleデータベースへ接続するためのデータソース名となります。接続文字列を適切に設定したら、次にASP.NET WEBアプリケーションを実行してみましょう。VS.NETのメニュー「デバッグ(D)」−>「開始(S)」を選択して実行します。



 以上のようにInputManのコントロールを使用したWindowsフォームの画面が確認できます。


 InputManからODP.NETの利用

 では、実際にInputManのコンポーネントからODP.NETを利用してOracleに格納された情報の表示と入力をおこなってみましょう。

  DataSetとInputManの連携

 今回のサンプルアプリケーションでは、Oracleデータベースからデータを取得しDataSetに格納、DataSetの内容をInputManに連携して表示しています。実際の手順は以下のようになります。

- DataSetにデータを格納
Oracleデータベースからデータを取得しDataSetに格納する手順は以下のようになります。
  1. Oracleデータベースへのコネクションの設定
    Oracleへの接続するためのコネクションの設定を行います。Oracleへのコネクションを確立するためには、どのOracleデータベースへどんなユーザーで接続するかという情報を接続文字列として設定する必要があります。接続文字列はコードで記述することも可能ですが、Oracle Developer Tools for Visual Studio .NET(以下、ODT)を利用すると簡単です。ODTを利用したOracleデータベースへの接続について説明します。

    - Oracleエクスプローラにデータ接続の追加
    Oracleエクスプローラの「データ接続」を右クリックし、接続の追加(A)を選択します。



    - 接続先情報の入力
    Oracleデータベースへの接続情報を入力します。

    データソース名 <データソース名>
    ユーザー名 inputman
    パスワード oracle



    データソース名はNetwork Configuration Assistant(以下、netca)で設定されたデータソース名を指定します。ユーザー名は「inputman」、パスワードに「oracle」と指定します。入力された情報が正しいか確認するために、「テスト接続(T)」をクリックすると、以下の画面が表示されます。



    接続が失敗した場合は、再度接続文字列、ユーザー名、パスワードの内容が正しいか確認をおこなってください。テストが終了後、「接続を追加」ウィンドウで「OK」ボタンをクリックすると、「Oracleエクスプローラ」に接続情報が追加されます。



  2. DataAdapterの設定
    Oracleデータベースへの接続情報の設定が完了したら、次にDataAdapterの設定をおこない、DataSetへ格納する情報の設定をおこないます。DataAdapterの設定もODTを使用します。Oracleエクスプローラから対象表を選択し、デザインウィンドウにドラッグ・アンド・ドロップします。



    ドラッグ・アンド・ドロップ後に、パスワード保存のダイアログが表示されますので、「はい(Y)」をクリックします。



    以上の作業でDataAdapterの作成は完了です。DataAdapterオブジェクトとConnectionオブジェクトが自動生成されているのが、デザインウィンドウで確認できます。



    今回は、以下の2つのテーブルから情報を取得しています。

    − EMPLOYEE(社員情報テーブル)
    − DEPARTMENT(部署テーブル)

    Oracleエクスプローラからテーブルをドラッグ・アンド・ドロップした場合にはDataAdapterのSelectCommand、CommandTextプロパティの内容は以下のようなドラッグ・アンド・ドロップされた単一テーブルのSQLが設定されています。

    SELECT * FROM EMPLOYEE


    SQLの変更は直接CommandTextプロパティの内容を変更します。



  3. DataSetへのデータの格納
    DataAdapterの設定が完了したら、次にDataSetにデータを格納するための手順について説明します。上記作業で作成したDataAdapterオブジェクトを右クリックし、「DataSetを生成...」を選択します。



    以上の作業でDataSetオブジェクトが自動生成されたのがデザインウィンドウから確認できます。



    また、ODTを使用してDataSetオブジェクトを生成すると、型付データセットとして生成され、XMLスキーマファイル(xsdファイル)も自動生成されます。



    ODTにより作成されたDataAdapterからDataSetへのデータの格納は以下のようなコードになります。

    empOracleDataAdapter1.Fill(Emp11.Emp)


    上記コードはDataAdapterのFillメソッドを使用してDataSetにデータを格納しています。今までの説明でDataSetに格納するまではODTを利用することにより簡単におこなえるのが確認できたと思います。今回のサンプルアプリケーションもODTを使用して開発されていますので、今まで説明した内容はサンプルアプリケーションを参照することにより確認できます。次にDataSetの内容をInputManの各コンポーネントを使用して表示してみましょう。
- DataSetとInputManコンポーネントの連携
DataSetに格納された内容をInputManコンポーネントに連携するには、InputManコンポーネントの「DataBindings」プロパティを設定します。「DataBindings」プロパティの設定はコードで記述することも可能ですが、プロパティウィンドウで設定することも可能です。



コードで記述する場合は、DataSetオブジェクトの内容をテキストコントロールのDataBindingsプロパティに設定します。DataBindingsプロパティが参照するControlBindingsCollectionオブジェクトのAddメソッドの引数には、次のように設定します。

第1引数:データをバインドするプロパティ名(文字列型)
第2引数:対象となるDataSetオブジェクト
第3引数:データをバインドするテーブルと列名(文字列型)

edtName.DataBindings.Add("Text", Me.Employee11, "Employee.ENAME")

DataBindingsプロパティの詳細については、VS.NETのヘルプの「Control.DataBindingsプロパティ」を参照してください。

  BLOB型フィールドへの対応

 画像などを扱うBLOBフィールドの内容もInputManのコンポーネントで表示することが可能です。今回のサンプルアプリケーションでは実際にBLOBフィールドに格納された社員のイメージ情報をInputManのリストボックスコントロールとコンボボックスコントロールで表示しています。



 「employee」テーブルの画像が格納されたBLOBフィールドである「ephoto」列を表示するには、まずInputManのリストボックス、もしくはコンボボックスの「ImageMember」プロパティに「ephoto」列を指定します。



 次に、ListBoxStyleプロパティとTextプロパティの値を画像が表示できるように設定します。



 以上のようにInputManの標準の機能を利用することで、簡単にOracleデータベース内に格納されているBLOBフィールドの画像を表示できるのが確認できたかと思います。
 ListBoxStyleとTextBoxStyleプロパティの内容はそれぞれ以下のようになります。

プロパティ値 − GrapeCity.Win.Input.ListBoxStyle 型
(既定値:ListBoxStyle.Text)

ListBoxStyleの値 説明
0 - Image 項目の画像だけを表示します。
1 - Text Text 項目の内容だけを表示します。
2 - Both Both 項目の画像と内容を表示します。
3 - ImageWithDescription ImageWithDescription 項目の画像と説明を表示します。
4 - TextWithDescription TextWithDescription 項目の内容と説明を表示します。
5 - BothWithDescription BothWithDescription 項目の画像、内容、および説明を表示します。

プロパティ値 − GrapeCity.Win.Input.TextBoxStyle 型
(既定値:GrapeCity.Win.Input.TextBoxStyle.TextOnly)

ListBoxStyleの値 説明
0 - ImageOnly テキストボックスに画像だけが表示されます。
1 - TextOnly テキストボックスに文字列だけが表示されます。
2 - Both テキストボックスに画像と文字列の両方が表示されます。

各プロパティの詳細についてはInputManのマニュアルを参照してください。

  Oracleフィールド属性の自動設定

 今回のサンプルでは、「dynamicSetProperties()」メソッドを利用して、「employee」テーブルのフィールド属性を取得し、InputManのプロパティに設定しています。文字列フィールドの場合は、入力文字列の長さを設定するためにInputManのEditコンポーネントMaxLengthプロパティの値を設定しています。また、数値列に関しては、Oracleの数値列から桁数を取得し、InputManのNumberコンポーネントFormatプロパティにセットしています。具体的な手順は以下のようになります。

- GetSchemaTable メソッドを使用して列情報を取得
ODP.NETに含まれている「OracleDataReader」オブジェクトの GetSchemaTable メソッドを使用して、列スキーマ情報を取得する方法について説明します。列スキーマは、フィールド プロパティとも呼ばれます。列スキーマ情報には、列に関する次のような情報が含まれます。
  • 名前
  • データ型
  • サイズ
  • その列が主キーのフィールドかどうか
  • その列がオートナンバー (AutoIncrement) 型のフィールドかどうか
GetSchemaTableメソッドを利用したコードは今回のサンプルコードを参照してください。

' ========
' テーブルのスキーマを動的に取得する
' ========
Private Function getDynamicSchema() As DataTable

 '' テーブルスキーマ情報の取得
 Dim aCMD As OracleCommand
 Dim rdr As OracleDataReader

 aCMD = empOracleDataAdapter1.SelectCommand
 aCMD.Connection.Open()
 rdr = aCMD.ExecuteReader()
 getDynamicSchema = rdr.GetSchemaTable
 aCMD.Connection.Close()

End Function

- 列スキーマ情報により、各コントロールのフォーマットを設定
GetSchemaTableメソッドを使用して取得した列スキーマ情報をもとに、各コントロールのフォーマットプロパティを設定します。

' ========
' テーブルスキーマにより、各コントロールのフォーマットを設定する
' ========
Private Sub dynamicSetProperties()

 Dim schemaTable As DataTable
 Dim datarowTmp As DataRow

 Dim NumericPrecision As Integer
 Dim NumericScale As Integer
 Dim str As String

 '' EMPテーブルのスキーマを取得する
 schemaTable = getDynamicSchema()

 '' ENAME
 datarowTmp = schemaTable.Rows(1)
 Me.edtName.MaxLength = datarowTmp(2)

 '' JOB
 datarowTmp = schemaTable.Rows(2)
 Me.edtJob.MaxLength = datarowTmp(2)

 '' SALARY
 datarowTmp = schemaTable.Rows(5)
 NumericPrecision = datarowTmp(3)
 NumericScale = datarowTmp(4)
 If NumericScale = 0 Then
  str = Space(NumericPrecision)
 Else
  str = Space(NumericPrecision) + "." + Space(NumericScale)
 End If
 str = str.Replace(" ", "#")
 Me.numSalary.Format.Digit = str

End Sub

列スキーマ情報を格納した「schemaTable」オブジェクトのRowsプロパティには、「employee」テーブルの列数分の情報が格納されています。Rowsプロパティ中の中に詳細な列情報が格納されており、その情報を取得してプロパティの値をセットしています。



GetSchemaTableメソッドを使用して取得した列スキーマ情報についての詳細は、VS.NETのヘルプの「GetSchemaTable メソッド」を参照してください。
以上のように、Oracleデータベース上に格納されたスキーマ情報をもとに、InputManの入力プロパティの値をセットし、フィールド定義情報にもとづいた入力項目を作成することが可能です。

  SafeMappingについて

 InputManのコンポーネントとOracleデータベースのデータを連携する場合に、今回のサンプルで紹介したようにDataSetを利用します。この場合、OracleDataAdapterを使用してOracleデータベースのデータをDataSetに取り込みますが、Oracle固有のデータ型は、暗黙的にOracleのデータ型に最適な.NETのデータ型に変換されます。しかし、双方のデータ型の特性からDataSetにデータを取り込んで処理する際に、データが失われる危険性が存在しています。具体的には、以下の表のOracleデータ型が該当します。

  データ型 最小値 最大値
1 Oracle NUMBER 最大38精度
.NET Decimal 最大28精度
2 Oracle DATE 紀元前4712年1月1日 紀元9999年12月31
.NET Datetime 紀元0001年1月1 紀元9999年12月31
3 Oracle TIMESTAMP 紀元前4712年1月1日
00:00:00.000000000
紀元9999年12月31
23:59:59.999999999
.NET Datetime 紀元0001年1月1
00:00:00. 0000000
紀元9999年12月31
23.59.59.9999999
4 Oracle INTERVAL
DAY TO
SECOND
-999999999
23:59:59.999999999
+999999999
23:59:59.999999999
.NET TimeSpan -10675199
02:48:05.4775808
+10675199
02:48:05.4775808


 このような場合に、ODP.NETでは、OracleDataAdapaterのSafeMappingプロパティを使用することにより、Oracleデータ型をDataSetにおいて、.NETのString型、もしくはOracle書式での.NETのbyte[]で表すことにより、データ損失の危険性を防ぐことが可能です。しかしながら、表の値をみても分かるとおり、多くの業務アプリケーションにおいては問題となる場合がないと考えられます。よって今回はDATE型を例にしたSafeMappingのみ解説いたします。

-<省略> -
cmd.CommandText = "SELECT empno, hiredate FROM employee"
Dim da As New OracleDataAdapter(cmd)
da.SafeMapping.Add("HIREDATE", GetType(System.String))

Dim ds As New DataSet
If ds.Tables.Contains("employee") Then ds.Tables("employee").Clear()
da.Fill(ds, "employee")
-<省略> -


 設計時に列名が不明な場合は、アスタリスク(*)を使用すると、データベース型のすべての列を安全な.NETタイプにマップできます。

da.SafeMapping.Add("*", GetType(System.String))


その他の型の詳細に関しましては、ODP.NETのマニュアル「Oracle Data Provider for .NET開発者ガイド」を参照してください。

メモ:SafeMappingにて指定する列名に関しては、必ず大文字で設定する必要があります。
    また、SELECT文で別名を指定している場合は、その別名を適切に指定してください。

    例)別名を指定している場合
      SELECT empno, hiredate as 入社日 FROM emp
      da.SafeMapping.Add("入社日", GetType(System.String))


 今まで説明したように、ODP.NETとInputManで使用するコンポーネントの親和性は非常に優れています。ODP.NETを利用することによりOracleデータベースに高速にアクセス可能なアプリケーションを開発することが可能です。また、ODTを利用すればアプリケーションの開発生産性を高め、さらにInputManを組み合わせることにより洗練された外観とインタフェースを簡単に実現にできます。是非お試しください。