特集

ASP.NETで実践するO/Rマッピング(NHibernate編)

山田 祥寛(http://www.wings.msn.to/
2005/09/21

Page1 Page2 Page3 Page4

NHibernate経由でデータベースを検索する

 以上で、NHibernateを利用するための準備は完了だ。それでは、いよいよNHibernate経由でデータベースにアクセスしてみよう。

 まず以下のWebフォームは、フォームの[出版社]欄に入力されたキーワードでbooksテーブルを検索し、取得した結果をDataGridコントロール上に一覧表示するサンプルだ。まずは具体的なコードを眺めてみよう。

<%@ Page ContentType="text/html" Language="C#" %>
<%@ Import Namespace="System.Collections" %>
<%@ Import Namespace="NHibernate" %>
<%@ Import Namespace="NHibernate.Cfg" %>
<%@ Import Namespace="NHibernate.Expression" %>
<%@ Import Namespace="Com.Msn.Wings" %>

<script runat="Server">

IList books = null;

// [検索]ボタンをクリックしたタイミングで実行
public void btnSrch_Click(Object sender, EventArgs e) {

  // NHibernateのセッションを開く
  Configuration config = new Configuration();
  config.AddAssembly("Book");
  ISessionFactory factory = config.BuildSessionFactory();
  ISession sess = factory.OpenSession();

  // 検索条件を設定(Publishフィールドを検索キーに、
  // Publishedフィールドで降順ソートを行う)
  ICriteria criteria = sess.CreateCriteria(typeof(Book));
  criteria.Add(Expression.Like("Publish", txtSrch.Text));
  criteria.AddOrder(Order.Desc("Published"));

  // 指定された条件に基づいて、検索処理を実行
  books = criteria.List();

  // DataGridコントロールにデータバインド
  grid.DataBind();
  sess.Close();
}

</script>
<html>
<head>
<title>NHibernateによるデータ・アクセス</title>
</head>
<body>
<form runat="Server">
  出版社:
  <asp:TextBox id="txtSrch" runat="Server" />
  <asp:Button id="btnSrch" runat="Server"
    Text="検索" OnClick="btnSrch_Click" />
  <br />

  <asp:DataGrid id="grid" runat="Server"
    DataSource="<%# books %>" AutoGenerateColumns="False"
    DataKeyField="isbn">

    <HeaderStyle BackColor="#BB2255" ForeColor="white"
      HorizontalAlign="Center" Font-Bold="True" />
    <ItemStyle BackColor="#FFeeEE" />
    <AlternatingItemStyle BackColor="#FFDDDD" />

    <Columns>
      <asp:BoundColumn DataField="Isbn" HeaderText="ISBNコード"
        ReadOnly="True" />
      <asp:BoundColumn DataField="Title" HeaderText="書名" />
      <asp:BoundColumn DataField="Price" HeaderText="価格"
        DataFormatString="{0:#,###円}" />
      <asp:BoundColumn DataField="Publish" HeaderText="出版社" />
      <asp:BoundColumn DataField="Published" HeaderText="配本日"
        DataFormatString="{0:yyyy年MM月dd日(ddd)}" />
    </Columns>

  </asp:DataGrid>

</form>
</body>
</html>
<%@ Page ContentType="text/html" Language="VB" %>
<%@ Import Namespace="System.Collections" %>
<%@ Import Namespace="NHibernate" %>
<%@ Import Namespace="NHibernate.Cfg" %>
<%@ Import Namespace="NHibernate.Expression" %>
<%@ Import Namespace="Com.Msn.Wings" %>

<script runat="Server">

Dim books As IList

' [検索]ボタンをクリックしたタイミングで実行
Public Sub btnSrch_Click(sender AS Object, e As EventArgs)

  ' NHibernateのセッションを開く
  Dim config As New NHibernate.Cfg.Configuration()
  config.AddAssembly("Book")
  Dim factory As ISessionFactory = config.BuildSessionFactory()
  Dim sess As ISession=factory.OpenSession()

  ' 検索条件を設定(Publishフィールドを検索キーに、
  ' Publishedフィールドで降順ソートを行う)
  Dim criteria As ICriteria = sess.CreateCriteria(GetType(Book))
  criteria.Add(NHibernate.Expression.Expression.Eq("Publish", txtSrch.Text))
  criteria.AddOrder(Order.Desc("Published"))

  ' 指定された条件に基づいて、検索処理を実行
  books = criteria.List()

  ' DataGridコントロールにデータバインド
  grid.DataBind()
  sess.Close()
End Sub

</script>
<html>
<head>
<title>NHibernateによるデータベース・アクセス</title>
</head>
<body>
<form runat="Server">
  出版社:
  <asp:TextBox id="txtSrch" runat="Server" />
  <asp:Button id="btnSrch" runat="Server"
    Text="検索" OnClick="btnSrch_Click" />
  <br />

  <asp:DataGrid id="grid" runat="Server"
    DataSource="<%# books %>" AutoGenerateColumns="False"
    DataKeyField="isbn">

    <HeaderStyle BackColor="#BB2255" ForeColor="white"
      HorizontalAlign="Center" Font-Bold="True" />
    <ItemStyle BackColor="#FFeeEE" />
    <AlternatingItemStyle BackColor="#FFDDDD" />

    <Columns>
      <asp:BoundColumn DataField="Isbn" HeaderText="ISBNコード"
        ReadOnly="True" />
      <asp:BoundColumn DataField="Title" HeaderText="書名" />
      <asp:BoundColumn DataField="Price" HeaderText="価格"
        DataFormatString="{0:#,###円}" />
      <asp:BoundColumn DataField="Publish" HeaderText="出版社" />
      <asp:BoundColumn DataField="Published" HeaderText="配本日"
        DataFormatString="{0:yyyy年MM月dd日(ddd)}" />
    </Columns>

  </asp:DataGrid>

</form>
</body>
NHibernateを利用してデータベース検索を行うサンプル・プログラム
(上:C#版「nhibernate_cs.aspx」、下:VB.NET版「nhibernate_vb.aspx」)

 NHibernateを利用する際に注目すべきポイントは、以下の2点だ。

(1)データベース操作の中核を担うのはISessionオブジェクト

 NHibernateにおいて、データベース・アクセスの中核的な役割を果たすのはISessionインターフェイスだ。ISessionオブジェクトは、Configurationクラス(NHibernate.Cfg名前空間)とISessionFactoryインターフェイス(NHibernate名前空間)を介して取得することができる。

 Configurationクラスはマッピング・ファイルの読み込みを管理するためのクラス、ISessionFactoryインターフェイスはISessionオブジェクトの生成を行うためのインターフェイスだ。

(2)条件式を管理するのはICriteriaオブジェクト

 テーブル検索時の条件句を表現するのは、ICriteriaインターフェイスの役割だ。ICriteriaオブジェクトは、ISession.CreateCriteriaメソッドから作成できる。

 ICriteriaインターフェイスには多くのメソッドが用意されているが、特に押さえておきたいのはAddメソッドおよびAddOrderメソッドだ。AddメソッドはWHERE句を、AddOrderメソッドはORDER BY句を追加するためのメソッドである。条件式、ソート順は、Expression、Orderクラス(いずれもNHibernate.Expression名前空間)を介して表現することが可能だ。

 以下に、ExpressionクラスとOrderクラスで利用可能な主なメソッドを示しておこう。

メソッド 概要
And(ICriterion lhs,ICriterion rhs) 条件式lhsとrhsとの集合積
Between(string pName, object lo, object hi) プロパティpNameの値がlo〜hiの間
Eq(string pName,object value) プロパティpNameの値がvalueに等しい
Ge(string pName,object value) プロパティpNameの値がvalue以上
Gt(string pName,object value) プロパティpNameの値がvalueより大きい
In(string pName,Object[] values) プロパティpNameの値がvaluesのいずれかの値
IsNotNull(string pName) プロパティpNameの値がNULLでない
IsNull(string pName) プロパティpNameの値がNULLである
Le(string pName,object value) プロパティpNameの値がvalue以下
Like(string pName,object value) プロパティpNameの値にvalueを含む(あいまい検索)
Lt(string pName,object value) プロパティpNameの値がvalue未満
Not(ICriterion expression) 条件式expressionの否定
Or(ICriterion lhs,ICriterion rhs) 条件式lhsとrhsとの集合和
Expressionクラスで利用可能な主なメソッド
 
メソッド 概要
Asc(string pName) プロパティpNameについて昇順
Desc(string pName) プロパティpNameについて降順
Orderクラスで利用可能な主なメソッド

 本稿では、publishフィールドをテキストボックス「txtSrch」の値で検索し、その結果をpublishedフィールドについて降順でソートした結果を取得している。つまり、見慣れたSQL命令に置き換えるならば、以下のようなSQLが発行されていると思っていただければよい。

SELECT * FROM books WHERE publish='*****' ORDER BY published DESC

 ICriteriaオブジェクトに必要な条件句を設定できたら、ICriteria.Listメソッドで検索処理を実行する。ListメソッドはIListオブジェクトを返すので、あとはこれをDataGridなどのデータ連結コントロールにバインドするだけだ。

■サンプル・プログラムの実行例

 以上が理解できたら、さっそくサンプルを動かしてみよう。以下のように入力された出版社に属する書籍情報だけが表示されれば成功だ。

データベース検索サンプル・プログラムの実行例
[出版社]欄に入力された文字列で検索処理を実行。検索結果はDataGridコントロールにバインドし、一覧表示する

■主キーによる検索

 検索処理を行うのはICriteria.Listメソッドばかりではない。例えば、主キーによる検索を行いたい場合には、ISession.Loadメソッドを利用することもできる。以下のコード例はbooksテーブルの主キーであるISBNコードでデータベースを検索する例だ(C#の例)。

Book book = (Book)sess.Load(typeof(Book),"4-8443-2061-0");

 主キーによるピンポイント検索を行いたいならば、ICriteriaオブジェクトを介するよりもLoadメソッドを用いた方が、結果データにも直接的なアクセスができるので、コードをシンプルにすることができるだろう。

■専用クエリ言語HQLによる検索条件の指定

 また、複雑な条件式を指定したい場合には、ICriteriaオブジェクトによる指定ではかえって分かりにくく、コードの可読性も低下する可能性がある。

 そのような場合には、NHibernateに用意されている専用のクエリ言語である「HQL(Hibernate Query Language)」の利用を検討してもよいだろう。HQLはSQLによく似たシンプルな問い合わせ言語だ(詳細は先述のNHibernateマニュアルを参照いただきたい)。

 以下は、HQLで上記サンプルの検索を置き換えたものだ(C#の例)。

books = sess.Find("FROM Book WHERE Publish = ? ORDER BY Published DESC", txtSrch.Text,TypeFactory.GetStringType());

 HQLクエリを発行するには、ISessionインターフェイスのFindメソッドを使用すればよい。Findメソッドの一般的な構文は、以下のとおり。

IList Find(string query)
IList Find(string query, object value, IType type)
IList Find(string query, object[] value, IType[] type)
HQLを利用するためのISessionインターフェイスのFindメソッドの構文

 引数query(HQLクエリ)には「?」の形式でパラメータのプレイスホルダを含めることが可能だ。

 プレイスホルダを含んだHQLクエリを使用する場合には、第2引数でパラメータを、第3引数でパラメータのデータ型を指定する。データ型を表すITypeオブジェクトを生成するには、TypeFactory.GetXxxxxTypeメソッドを使用できる。TypeFactoryクラスで利用可能な主なGetXxxxxTypeメソッドを以下に示しておく。

GetAnsiStringType GetBinaryType GetBooleanType GetByteType
GetDateTimeType GetDateType GetDecimalType GetDoubleType
GetGuidType GetCharType GetInt16Type GetInt32Type
GetInt64Type GetObjectType GetSByteType GetSingleType
GetStringType GetTimeSpanType GetTimestampType GetTimeType
GetTrueFalseType GetYesNoType
TypeFactoryクラスで利用可能なGetXxxxxTypeメソッド
 

 INDEX
  [特集] ASP.NETで実践するO/Rマッピング(NHibernate編)
    1..NETの向けのO/Rマッピング・ツール
    2.NHibernateのインストールと設定手順
  3.NHibernate経由でデータベースを検索する
    4.NHibernateによるデータ登録
 


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間