ASP.NET Dynamic Data Applicationの概要
Dynamic Dataは、データドリブンのWebアプリケーションを簡単に構築するためのアプリケーション基盤です。実装はASP.NETと、LINQ to SQLもしくはLINQ to Entitiesを利用しています。
Dynamic Dataは非常に柔軟で、データのリソースから推論し、ページ作成時に最適な要素を選択し、データを表示する要素を動的に変更します。また、既定のテンプレートに基づいてデータのViewをカスタマイズすることもできます。
データドリブンのWebアプリケーションとして簡単に作成できるDynamic Dataは魅力的ですが、現場での活用シナリオはWeb版の簡易マスタメンテとしての利用が最適なのかもという印象を受けます。一括取り込み、一括削除などは、現時点ではLINQの制約から難しいので、1つずつの項目の編集、追加や全体を鳥瞰するという用途であれば便利なアプリケーションが構築できるかと思います。
実際にDynamic Dataを実行した画面は図1のようになります。
それでは、Dynamic Dataの中で注目すべきポイントについて解説します。
Dynamic Dataのデータ取得
Dynamic Dataはオブジェクトモデルのメタデータからのデータフィールドのレンダリングについての基本情報を取得します(MetaModel
クラス)。また、オブジェクトモデルを通してメタデータに情報を加えるための機能を提供し、情報はカスタムValidation(検証コントロール)とデータフィールドに使用されます(DataAnnotations名前空間)。
MetaModelクラス
MetaModel
クラスとはDynamic Dataのデータで使われるデータベースと、データコンテキストのことを指します。Dynamic Dataでは、データがLINQ to SQLとADO.NET Entity Frameworkに基づくモデルをサポートします。
データコンテキストは、データベース接続オブジェクトとして利用され、データモデルはCLRの型と同様にデータベースのデータ構造を表すオブジェクトとして利用されます。
主に、DynamicDataの中では、実行時のモデルの有無のチェックや、ルーティング登録時に利用されます。
DataAnnotations名前空間
System.ComponentModel.DataAnnotations名前空間は、データモデルのメタデータを編集する属性クラスを提供する名前空間です。
メタデータの編集は、テーブルと同名のパーシャルクラスによる指定で表示設定や、検証コントロールの表示などの情報を設定します。
クラス | 概要 |
DataTypeAttribute | データフィールドと紐づく型を指定 |
DisplayColumnAttribute | 外部キーのカラムとして照会されたテーブルで表示されるカラムを指定 |
DisplayFormatAttribute | データフィールドを表示するフォーマットを指定 |
MetadataTypeAttribute | データモデルとパーシャルクラスを紐付けるためにメタデータクラスを指定 |
RangeAttribute | データフィールドで許容される数字の範囲を指定 |
RegularExpressionAttribute | データフィールドの値を表示する正規表現の指定 |
RequiredAttribute | データフィールドの値で入力必須のエラーメッセージを指定 |
ScaffoldColumnAttribute | クラスかデータカラムの表示の可否を指定 |
ScaffoldTableAttribute | クラスかテーブルの表示の可否を指定 |
StringLengthAttribute | データフィールドで許容される文字の最大数を指定 |
UIHintAttribute | データフィールドを表示するテンプレートかユーザーコントロールを指定 |
ValidationAttribute | すべての検証属性のベースクラス |
ValidationException | ValidationAttributeクラス使用時に、データフィールドの検証の間、発生する例外を表示 |
DynamicDataManagerコントロール
Dynamic Dataを利用する上で欠かせないのがDynamicDataManagerコントロールです。これは、ASP.NET AJAXのScriptManagerコントロール同様で、Dynamic Dataを利用するページには必須のコントロールです。また、Dynamic Dataを利用するコントロールよりも前に配置する必要があります。以下のソースはプロジェクト作成時に自動生成されます。
フォームデザイナ側の具体的な設定はAutoLoadForeignKeys
プロパティ(Boolean型による設定)のみです。このプロパティは外部キーがLINQ to SQLのデータコンテキストに自動で認識するかどうかを設定します。
<asp:DynamicDataManager ID="DynamicDataManager1" runat="server" AutoLoadForeignKeys="true" />
コードビハインド側では、DynamicDataManagerコントロールを通じて、あらかじめ用意したメタモデルをバインドするためにデータコントロールを登録します。
Protected Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) ' GridView1にメタモデルをバインドする DynamicDataManager1.RegisterControl(GridView1, True) End Sub
Dynamic Data FieldTemplate
Dynamic Dataのプロジェクトを作成すると、FieldTemplateフォルダが作成されます。このフォルダにはさまざまなDynamic Dataフィールドコントロールが用意されています。Dynamic Dataは、データモデルのリソースから推論し、ページを作成時に、このFieldTemplateフォルダの中から最適な要素を選択し、データを表示する要素を動的に変更します。つまり、既にコードビハインド側のソースも自動生成されています。
プロジェクト作成時に用意されるDynamic Dataフィールドコントロールは次のとおりです。
コントロール | 概要 |
Boolean.ascx | Boolean型のデータを表示するのに利用(チェックボックス) |
Boolean_Edit.ascx | 編集画面の時にBoolean型のデータを表示するのに利用(チェックボックス) |
Children.ascx | リレーションシップを持つデータをリレーションシップのあるページへとリダイレクトさせるのに利用(ハイパーリンク) |
DateTime.ascx | 日付型のデータを表示するのに利用(リテラル) |
DateTime_Edit.ascx | 編集画面の時に日付型のデータを表示するのに利用(テキストボックス) |
Decimal_Edit.ascx | 編集画面の時にDecimal型のデータを表示するのに利用(テキストボックス) |
ForeignKey.ascx | 外部キーを持つデータを表示するのに利用(ハイパーリンク) |
ForeignKey_Edit.ascx | 編集画面の時に外部キーを持つデータを表示するのに利用(ドロップダウンリスト) |
Integer_Edit.ascx | 編集画面の時にInteger型のデータを表示するのに利用(チェックボックス) |
Text.ascx | String型、Decimal型、Double型、Int型、byte型、short型、long型のデータを表示するのに利用(リテラル) |
Text_Edit.ascx | 編集画面の時にString型、Decimal型、Double型、Int型、byte型、short型、long型のデータを表示するのに利用(テキストボックス) |
Multiline_Edit.ascx | 編集画面の時にテキストブロックを利用しているデータを表示するのに利用(テキストボックスのMultiLineモード) |
メタデータから上記のテキストフィールドをDynamicDataManagerコントロールが判断し、最適な形で表示します。この時、特に気になるのは、ForeignKey_Edit.ascxのデータ取得方法だと思いますが、ForeignKey_Edit.ascxはPopulateListControl
メソッドを利用して値をバンディングします。
PopulateListControlメソッド
PopulateListControl
メソッドは外部キーを持つデータを表示する時に、DropDownListコントロールに対して値をバインディングするために利用されるメソッドです。
PopulateListControl
メソッドは、外部キーを通して、現在のテーブルに関連があるデータテーブルのすべてのアイテムをListControl
オブジェクトにバインディングします(図3)。
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) ' DropDownList1のアイテムがない時 If (DropDownList1.Items.Count = 0) Then ' メタデータ列のフィールドで必須入力チェックをパスしているかどうか If Not Column.IsRequired Then ' DropDownList1のアイテムに["Not Set"]を追加 DropDownList1.Items.Add(New ListItem("[Not Set]", "")) End If ' 外部キーを通して、データテーブルのすべてのアイテムをDropDownList1にバインディングする PopulateListControl(DropDownList1) End If End Sub