LINQ to Entities その2

LINQ to Entities その2


【取得列を明示的に指定する(select句)】

select句を利用することで、特定のプロパティだけを取り出したり、加工したり
が可能になる。
以下のような加工をselect句で行った例
・Title列を先頭から5文字だけ
・ViewCount列を1000単位で
・Released列がtrueなら「発売中」、falseなら「発売予定」

[ArticlesController.vb]

ビューモデル
[Models\ArticleView.vb]

ArticleViewクラスは、ビューとして表示/操作すべきデータを表す。このようなモデルをビューモデルという。
Select句でビューモデルのインスタンス生成と同時に、Withによってプロパティの値を設定している。
arrow_down
[出力結果(画面)]
54
同じ内容をメソッド構文で表現した場合は以下のとおり
[ArticlesController.vb]

【重複のないデータを取得する(Distinctメソッド)】

Distinctメソッドを利用することによって、結果セットから重複したデータを除去できる。
(対応するクエリー式構文はない)
以下は、Commentsテーブルから重複しない名前を取得する例

コントローラー[CommentsController.vb]

ビュー[Distinct.vbhtml]

arrow_down
[出力結果(画面)]
55

【特定範囲のデータだけを取得する(Skip/Takeメソッド)】

・Skipメソッド:指定された件数だけデータを読み飛ばす。
・Takeメソッド:指定された件数のデータだけを取得する。
Skip/Takeメソッドを利用することでm~n件目のデータを抜き出すといった操作が可能となる。
(対応するクエリー式構文はない)

[データ]
57
コントローラー[ArticlesController.vb]

arrow_down
[出力結果(画面)]
56

ページング処理

Skip/Takeメソッドを利用することでページング処理も実装できる。
以下は3件単位でグリッドの表をページングする例

コントローラー[ArticlesController.vb]

arrow_down
[出力結果(画面)]
・「http://~/Articles/Paging」でアクセスした場合
58
・「http://~/Articles/Paging/2」でアクセスした場合
59

【先頭のデータを取得する(Firstメソッド)】

結果セットから先頭のデータを取得する場合、Firstメソッドが利用できる。
※以下はReturnでViewを返さず、Contentを返している。
 Contentを返す場合は、Viewファイルを用意しても使用されない(Viewファイル無しで実行できる)

コントローラー[ArticlesController.vb]

ビュー[無し]
arrow_down
[出力結果(画面)]
※ビュー無しのため、結果の文字列のみが表示される。
60

ただし、Firstメソッドは該当するデータが存在しない場合には、InvalidOperationException
の例外を発生するため、データが存在しない場合にその型のデフォルト値を返したい場合、
FirstOrDefaultメソッドを利用する。

コントローラー[ArticlesController.vb]

ビュー[無し]
arrow_down
[出力結果(画面)]
61

【データをグループ化する(group句)】

特定のキー列でデータをグループ化するには、group句またはGroupByメソッドを利用する。
group句(クエリー式構文)の方は、VBではどう記述すればいいのか分からなかった。
(C#と違って、Into が必要みたいだが、どうやっても上手くいかなかった
メソッド構文の方が簡単で、C#との置き換えが簡単なのでVBではメソッド構文を使用した方がよさそう。)
以下は、Articlesテーブルの内容をCategory列でグループ化して、それぞれに属するレコードを列挙する例

モデル[Article.vb]

モデル[CategoryEnum.vb]

コントローラー[ArticlesController.vb]

ビュー[Group.vbhtml]

データ
62
arrow_down
[出力結果(画面)]
63
GroupByメソッドによる戻り値は、IQueryable(Of IGrouping(Of TKey, TSource))型になる。
よって、最初のループでグループを取得し、次のループでその取得したグループ配下の要素(エンティティ)を取得する。


ちなみに、以下のようにすることで、UrlプロパティとTitleプロパティのみを含んだオブジェクトを返すようにできる。
(出力結果は同じになる)

コントローラー[ArticlesController.vb]

ビューは、IGroupingの第2引数をArticle→ArticleViewに変更する

【複数列でグループ化する】

複数列でグルーピングする場合、グループ化キーをオブジェクトとして指定する。
(グループ化キー用のビューモデルを準備しておき、オブジェクト生成時にプロパティに値を指定)
以下は、Category, Published列でグループ化した例

ビューモデル[ArticleGroup.vb]

コントローラー[ArticlesController.vb]

ビュー[MultiGroup.vbhtml]

arrow_down
[出力結果(画面)]
64

※また、a.Published.Yearのようにすれば、公開年でグループ化したりできる。

【グループ化した結果でフィルターする】

グルーピングされた結果に対して、追加でフィルターすることも可能。
その場合、GroupByメソッドの後にWhereメソッドでフィルタリングする。(HAVING句に相当)
※GroupByメソッド以降のWhereとSelectではラムダ式のパラメーターにはグループ化の結果が入る。
以下は、Category列でグループ化し、ViewCountの合計が6000以上のグループだけを表示する例

ビューモデル[ArticleHaving.vb]

コントローラー[ArticlesController.vb]

ビュー[Having.vbhtml]

データ
66
arrow_down
[出力結果(画面)]
65
※他にも以下の集計メソッドが利用できる。
・Average
・Count
・LongCount
・Max
・Min


同じ要領で、グループキーでソートすることもできる。
以下は、Category列でグループ化し、ViewCountの合計の降順に表示する例

コントローラー[ArticlesController.vb]

ビュー[Having2.vbhtml]

arrow_down
[出力結果(画面)]
67

【エンティティ同士を結合する(join句)】

join句またはJoinメソッドを使用することにより、特定のキー列でエンティティ同士を結合し、
複数のエンティティをまとめて取得することができる。(SQLの内部結合のようなもの)
以下は、ArticleエンティティとCommentエンティティを結合する例
(キーは、Articleエンティティ自体とCommentエンティティのArticleプロパティ)

モデル[Article.vb]

モデル[Comment.vb]

コントローラー[ArticlesController.vb] ※クエリー構文

コントローラー[ArticlesController.vb] ※メソッド構文

ビュー[Join.vbhtml]

[Articlesテーブル]
68
[Commentsテーブル]
69
arrow_down
[出力結果(画面)]
70