ScottGu's blog translated by Chica @ Wankuma

LINQ to SQL (パート 9 - カスタムLINQ文をasp:LinqDatasourceコントロールと共に使用)

  

  ここ何週間かLINQ to SQLをカバーしたブログ投稿をシリーズとしてを書いています。 LINQ to SQL とは、 .NET Framework 3.5リリースで出荷されるビルドインのO/RM ( オブジェクトリレーショナルマッピング)のことです。これにより、.NETクラスを使用してリレーショナルデータベースをモデル化することができます。LINQ文を使用してデータベースの検索、またデータの更新・挿入・削除も行うことができます。

以下はこのシリーズの最初の8つのパートです。:

シリーズのパート 5で.NET 3.5の新しい<asp:LinqDataSource>コントロールをご紹介し、LINQ to SQLデータモデルへASP.NET UIコントロールを簡単にバインドして使用する方法をお話ししました。新しい<asp:ListView>コントロールのお話をしたフォローアップ投稿でもその使用方法についてもう少しご紹介しました。(パート 1 - クリーンなCSS UIでProductリストページを構築

これらの記事の両方で実行したクエリは比較的標準的なものでした。(where節は1つのテーブルデータに対して動作します。)本日のブログ投稿では、LinqDataSourceコントロールと一緒にLINQの全てのクエリ表現をどのように使用するかについて、そしてそのコントロールとLINQ to SQLのクエリ文をどのように使用することができるかについてご紹介しようと思います。

要約: 宣言Whereステートメントと<asp:LinqDataSource>

これら2つ投稿で、LINQ to SQLデータモデル上でフィルタステートメントを宣言的に表現するために、LinqDataSourceコントロールのビルドインフィルタ機能をどのように使用することができるかについてご紹介しました。

例えば、LINQ to SQLデータモデルをNorthwindデータベースに対して作成した(このシリーズのパート 2で方法をカバーしています。)と仮定しますが、特定のカテゴリ("categorid"値のクエリストリングを通じて特定した)にある製品だけを返す宣言的な<where>フィルタがある<asp:LinqDataSource>コントロールをページ上に宣言することができます。

そうすると、データソースで<asp:gridview>コントロールをポイントすることができ、その上でページング、編集、ソートを行うことが可能になります。:

上記のページを起動すると、Productデータモデルに対して自動のソート、ページング、編集がサポートされたGridViewを取得することができます。:

宣言的な<where>パラメータを上記のように使用すれば多く場面で上手く利用できます。でも、もしよりリッチに、より複雑にProductフィルタリングをかけたい場合はどうすれば?例えば、動的に設定された国に拠点を置く供給者が製造した製品だけを表示したい場合はどうすれば?

<asp:LinqDataSource> 選択イベントを使用

カスタムクエリシナリオを処理するために、<asp:LinqDataSource>コントロール上で"Selecting"イベントを処理するイベントハンドラを実装することができます。このイベントハンドラ内では、データモデル結果を取得するどんなコードでも書くことができます。これは、LINQ to SQL クエリ文で行う、もしくはストアドプロシージャを呼び出す、もしくは カスタムSQL文を使用してLINQ to SQLデータモデルを取得することができます。一度一連のデータを取得すると、後はLinqDataSourceSelectEventArgs オブジェクト上の"Result"プロパティへそれを割当てるだけです。その後<asp:LinqDataSource>はこのシーケンスを処理するためのデータとして使用します。

例えば、以下のLINQ to SQLクエリ文は特定の国に拠点を置く供給者からの製品だけを取得します。

VB:

C#:

注: イベントハンドラ内でインラインのクエリ文を書く必要はありません。よりクリーンな方法にするには、ヘルパーメソッド内にカプセル化します。そうすればイベントハンドラから呼び出すだけになります。パート 8のブログ投稿の始めの方で(GetProductsByCategory ヘルパーメソッドを使用して)、これらのヘルパーメソッドの作成方法を1つご紹介しました。

カスタムのSelectingイベントハンドラを使用してページを起動すると、配列にある国にいる供給者の製品だけを見ることができます。

 

上記で非常にかっこいい事の1つは、カスタムSelectingイベントを使用してデータを取得していても、まだGridViewでページング、ソートが動作することです。このページング、ソートロジックはデータベースで起こります。 つまり、GridViewでは現在のページインデックスに表示する必要のある10個の製品をデータベースから引っ張ってくるだけだということです。(これにより非常に効率的になります。)

カスタムの選択イベントを使用した時に効率的なページング、ソートのサポートを取得することがどうして可能なのだろうと、自問自答されるかもしれません。理由はLINQが遅延実行モデルを使用しているからです。つまり、実際に結果にループしてアクセスするまでクエリが実行されないのです。この遅延実行モデルの利点の1つは、他のクエリから上手くクエリを取り出して作成し、効率的に"add-on"動作をそれらに追加できるようにします。これについては、LINQ to SQL パート 3のブログ投稿で詳細をご覧頂けます。

上記の"Selecting"イベントハンドラで、実行したいカスタムのLINQクエリを宣言し、それを"e.Result"プロパティに割り当てます。実際にまだそれは実行していません。(結果をループさせてない、またはToArray()またはToList()をその上で呼び出していないからです。) そのため、LINQDataSourceはクエリに対するSkip()やTake()演算子上に付加することができ、"orderby"文をそこへ適用することができます。これらの値は全て自動的にページインデックスとGridViewのソート設定から計算されます。その後、LINQDataSourceはLINQ文を実行しデータを取得するだけになります。そして、LINQ to SQLが確実にデータベースでソートとページングロジック(これは必要な10個の製品だけをそこから取得します。)が処理されるように手配します。

下記をご覧頂くと、カスタムのLinqDataSourceの"Selecting"イベントを使用している時でも、どのようにしてまだデータの編集や削除を行うためにGridViewが使用できるのかについてご確認頂けると思います。

Selectingイベントが結果シーケンスが標準のエンティティオブジェクト(例えば、Product、Supplier、Category、Order型などの一連のデータ)であるResultクエリを割り当てている限り、この編集・削除のサポートは有効です。そして、LINQDataSourceはUIコントロールがそれらに対して更新を実行するようなケースを自動的に処理することができます。

LINQ to SQLで更新をどのように行うかについての詳細は、このシリーズのパート 4をお読みください。そして、LinqDataSourceで更新が行われているところをご確認頂くには、このシリーズのパート 5をお読みください。

カスタムクエリの投影をSelectingイベントで実行

LINQの強力な機能の1つが"形成"や"投影"データのカスタマイズ機能です。LINQ to SQL文で、エンティティからサブセットの値のみを取得して表示し、そして/または、動的に新しい値をその場で定義してあるカスタム文を使用して計算させることができます。これらのLINQクエリの投影・形成機能についての詳細は、このシリーズのパート 3でご確認頂けます。

例えば、Product情報のカスタムセットを表示するためにGridViewに格納するよう"Selecting"イベントハンドラを修正することができます。このグリッドでは、この製品のID、製品名、単価、注文数、総収入を表示しようと思います。以下の様にLINQ文を使用してこれらの最後の2つの値を動的に計算することができます。:

VB:

C#:

注: 上記のRevenueステートメントで使用されているSumメソッドは拡張メソッドの1例です。それが取っている機能はラムダ式の1例です。LINQクエリ文で作成されている結果の型は匿名型です。それは、その形状がクエリ文から推測されているからです。拡張メソッド、ラムダ式、匿名型は、すべてVS 2008でのVBおよびC#の新しい言語機能です。

GridViewとバインドした時のカスタムLINQ文の結果は以下のUIのようになります。:

データに対してカスタムLINQの形成・投影を使用していても、ページング、ソートがGridViewでまだ機能していることを上記でご確認ください。

1つだけカスタムの形成・投影で動作しないものが、インラインの編集サポートです。これは、カスタムの投影をSelectingイベントで行っていると、LinqDataSourceは配下にあるエンティティオブジェクトを安全に更新する方法を知る術がないからです。カスタムに形成された型でGridViewに編集サポートを追加したい場合は、(更新を処理するカスタムのUpdateメソッドを供給することができる)ObjectDataSourceコントロールを使用して移動させるか、または更新を実行した時に新しいページにユーザナビゲートを設定して、そして編集するProductエンティティへバインドさせたDetailsViewまたはFormViewコントロールを表示させます。

まとめ

LinqDataSourceのビルドインの宣言的なフィルタリングサポートを使用して、LINQ to SQLデータモデルに対して簡単に通常のクエリ操作を実行することができます。

より上級なまたカスタムのフィルタリング文を有効にするために、LINQDataSourceのSelectingイベントを活用することができます。これによりLINQ to SQLデータを取得・フィルタリングするのにどんなロジックでも実行できるようになります。これを行うために、このデータの取得、LINQクエリ文の使用、ストアドプロシージャの呼び出し、またはカスタムSQL文の発生を行うメソッドを呼び出すことができます。

Hope this helps,

Scott

ScottGu's blog translated by Chica @ Wankuma 

※本翻訳に関しまして、Scottさんにはご了承頂いております。