2009年9月3日木曜日

Monoで他のDBも使ってみたよ!+(db4o、NHibernate編)5

このエントリーをはてなブックマークに追加

DBアクセス

接続確認

簡単な検索(全件検索、Idによる検索)を行うコードを用いて、NHibernateで用意されているクエリ機能(HQL、Criteria、Native SQL)を試します。

 ベースとなるコード(C#)は以下になります(各DBMS用NHibernateコンフィグファイルについては、「おまけ」の節に掲載します)。

[Productsテーブルの全件取得(Idの昇順)]
using System;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Criterion;

using NHibernateExample;

namespace NHibernateExample.Test
{
  public class Query1
  {
    public static void Main(string[] args)
    {
      string s;
      string cfg_prefix;

      // 接続先DBMSの選択
      START:
      Console.Write("Connect to\n1:SQLite\n2:PostgreSQL\n3:MySQL\n4:SQLServer\n5:Oracle\n6:Firebird\n7:DB2\n?> ");
      s = Console.ReadLine();
      switch(s)
      {
        case "1": cfg_prefix = "SQLite";     break; // SQLite
        case "2": cfg_prefix = "PostgreSQL"; break; // PostgreSQL
        case "3": cfg_prefix = "MySQL";      break; // MySQL
        case "4": cfg_prefix = "SQLServer";  break; // SQL Server
        case "5": cfg_prefix = "Oracle";     break; // Oracle
        case "6": cfg_prefix = "Firebird";   break; // Firebird
        case "7": cfg_prefix = "DB2";        break; // DB2
        default: goto START;
      }

      Configuration cfg = new Configuration();
      cfg.Configure(cfg_prefix + ".cfg.xml");
      ISessionFactory factory = cfg.BuildSessionFactory();

      using (ISession session = factory.OpenSession())
      {
        // Productsテーブルの全件取得(Idの昇順)
        #region Query

        // HQL
        var results = session.CreateQuery(
          "from Product as p order by p.Id asc")
          .List();

        #endregion

        foreach (Product p in results)
        {
          Console.WriteLine(p);
        }
      }
    }
  }
}
/*
* ビルド:
*
*   gmcs -r:NHibernate.dll,NHibernateExample.dll query1.cs
*
* 実行:
*
*   mono query1.exe
*
*/

[ProductsテーブルのIdによる検索]
using System;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Criterion;

using NHibernateExample;

namespace NHibernateExample.Test
{
  public class Query2
  {
    public static void Main(string[] args)
    {
      string s;
      string cfg_prefix;

      string i;
      int id;

      // 接続先DBMSの選択
      START:
      Console.Write("Connect to\n1:SQLite\n2:PostgreSQL\n3:MySQL\n4:SQLServer\n5:Oracle\n6:Firebird\n7:DB2\n?> ");
      s = Console.ReadLine();
      switch(s)
      {
        case "1": cfg_prefix = "SQLite";     break; // SQLite
        case "2": cfg_prefix = "PostgreSQL"; break; // PostgreSQL
        case "3": cfg_prefix = "MySQL";      break; // MySQL
        case "4": cfg_prefix = "SQLServer";  break; // SQL Server
        case "5": cfg_prefix = "Oracle";     break; // Oracle
        case "6": cfg_prefix = "Firebird";   break; // Firebird
        case "7": cfg_prefix = "DB2";        break; // DB2
        default: goto START;
      }

      Console.Write("ID?> ");
      i = Console.ReadLine();
      if (!(Int32.TryParse(i, out id)))
      {
        Console.WriteLine("整数値を入力して下さい。入力値 = {0}", i);
        return;
      }

      Configuration cfg = new Configuration();
      cfg.Configure(cfg_prefix + ".cfg.xml");
      ISessionFactory factory = cfg.BuildSessionFactory();

      using (ISession session = factory.OpenSession())
      {
        // ProductsテーブルのIdによる検索
        #region Query

        // HQL
        var result = session.CreateQuery(
          "from Product as p where p.Id = :id")
          .SetParameter("id", id)
          .UniqueResult<Product>();

        #endregion

        if (result != null)
        {
          Console.WriteLine("FOUND!:{0}", result);
        }
      }
    }
  }
}
/*
* ビルド:
*
*   gmcs -r:NHibernate.dll,NHibernateExample.dll query2.cs
*
* 実行:
*
*   mono query2.exe
*
*/
HQL
HQL(Hibernate Query Language)はNHibernateで用意されているSQLライクなクエリ言語です。

 NHibernateで用意されている各クエリは、SQLに変換されるので、コンフィグファイルで次の設定をした場合、
<property name="show_sql">true</property>
HQLが次のようにSQLに変換されるのが分かります。

[Productsテーブルの全件取得(Idの昇順)]
NHibernate: SELECT this_.ProductID as ProductID0_0_, this_.ProductName as ProductN2_0_0_, this_.Price as Price0_0_, this_.ProductDescription as ProductD4_0_0_ FROM Products this_ ORDER BY this_.ProductID asc

[ProductsテーブルのIdによる検索]
NHibernate: select product0_.ProductID as ProductID0_, product0_.ProductName as ProductN2_0_, product0_.Price as Price0_, product0_.ProductDescription as ProductD4_0_ from Products product0_ where (product0_.ProductID=@p0 ); @p0 = '1'

 また、HQLではありませんが、「Idによる検索」の様な、PRIMARY KEYによる検索の場合、次の記述が可能です。

[ProductsテーブルのIdによる検索]
var result = session.Get<Product>(id);
Criteria
HQLを次のCriteriaに置き換え可能です。

[Productsテーブルの全件取得(Idの昇順)]
// Criteria
var results = session.CreateCriteria(typeof(Product))
  .AddOrder(Order.Asc("Id"))
  .List();

[ProductsテーブルのIdによる検索]
// Criteria
var result = session.CreateCriteria(typeof(Product))
  .Add(Expression.Eq("Id", id))
  .UniqueResult<Product>();
CriteriaはHQLより簡易なクエリ機能と位置づけられているようです。
Native SQL
HQLを次のNative SQLに置き換え可能です。

[Productsテーブルの全件取得(Idの昇順)]
// Native SQL
var results = session.CreateSQLQuery(
  "SELECT * FROM Products ORDER BY ProductID")
  .AddEntity(typeof(Product))
  .List();

[ProductsテーブルのIdによる検索]
// Native SQL
var result = session.CreateSQLQuery(
  "SELECT * FROM Products WHERE ProductID = :id")
  .AddEntity(typeof(Product))
  .SetParameter("id", id)
  .UniqueResult<Product>();
上記の様に、直接SQL文を記述することが可能です。

 Monoで他のDBも使ってみたよ!+(db4o、NHibernate編)6 へ続く。

0 件のコメント:

コメントを投稿