2009年9月4日金曜日

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

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

動作確認

基本的なDB操作(登録、更新、削除)を確認するために、以下のコード(C#)を使用します。使用するコードは「db4o編」の動作確認で使用したのと同様の構造で、操作上の違いはありません。

 作業する上でのディレクトリ構造は、下表の通りとします。

ディレクトリファイル
~/src/cs/NHibernateExampleIProductRepository.cs
~/src/cs/NHibernateExample/Testclient.cs
~/src/cs/NHibernateExample/TestDataProductRepository.cs, TestDataHelper.cs
IProductRepositoryインターフェース、ProductRepository、TestDataHelperクラス
[IProductRepository.cs]
using System;

namespace NHibernateExample
{
  public interface IProductRepository : IDisposable
  {
    void Add(Product product);
    void Update(Product product);
    void Remove(Product product);
    void GetAll();
  }
}

[ProductRepository.cs]
 登録:ISession#Save、更新:ISession#Update、削除:ISession#Delete メソッドを使用します。
using System;
using System.Collections.Generic;
using System.Linq;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Criterion;

using NHibernateExample;

namespace NHibernateExample.TestData
{
  public class ProductRepository : IProductRepository
  {
    private static IList<Product> _cache;

    public void Add(Product product)
    {
      using (ISession session = TestDataHelper.OpenSession())
      using (ITransaction tran = session.BeginTransaction())
      {
        Product r1 = _getByIdFromCache(product.Id);
        if (r1 != null)
        {
          Console.WriteLine("Add:既にデータあり #1");
          return;
        }

        Product r2 = _getById(session, product.Id);
        if (r2 != null)
        {
          Console.WriteLine("Add:既にデータあり #2");
          return;
        }

        try
        {
          session.Save(product);
          tran.Commit();
        }
        catch(Exception ex)
        {
          Console.WriteLine("例外: {0}", ex.Message);
          tran.Rollback();
        }
      }
    }

    public void Update(Product product)
    {
      using (ISession session = TestDataHelper.OpenSession())
      using (ITransaction tran = session.BeginTransaction())
      {
        Product r1 = _getByIdFromCache(product.Id);
        if (r1 == null)
        {
          Console.WriteLine("Update:該当データなし #1");
          return;
        }

        Product r2 = _getByProduct(session, r1);
        if (r2 == null)
        {
          Console.WriteLine("Update:該当データなし #2");
          return;
        }

        r2.Name        = product.Name;
        r2.Price       = product.Price;
        r2.Description = product.Description;

        try
        {
          session.Update(r2);
          tran.Commit();
        }
        catch(Exception ex)
        {
          Console.WriteLine("例外: {0}", ex.Message);
          tran.Rollback();
        }
      }
    }

    public void Remove(Product product)
    {
      using (ISession session = TestDataHelper.OpenSession())
      using (ITransaction tran = session.BeginTransaction())
      {
        Product r1 = _getByIdFromCache(product.Id);
        if (r1 == null)
        {
          Console.WriteLine("Remove:該当データなし #1");
          return;
        }

        Product r2 = _getByProduct(session, r1);
        if (r2 == null)
        {
          Console.WriteLine("Remove:該当データなし #2");
          return;
        }

        try
        {
          session.Delete(r2);
          tran.Commit();
        }
        catch(Exception ex)
        {
          Console.WriteLine("例外: {0}", ex.Message);
          tran.Rollback();
        }
      }
    }

    public void GetAll()
    {
      using (ISession session = TestDataHelper.OpenSession())
      {
        _cache = session.CreateCriteria(typeof(Product))
          .AddOrder(Order.Asc("Id"))
          .List<Product>();

        foreach (Product p in _cache)
        {
          Console.WriteLine(p);
        }
      }
    }

    public void Dispose()
    {
    }

    private Product _getById(ISession session, int id)
    {
      return session.Get<Product>(id);
    }

    private Product _getByIdFromCache(int id)
    {
      return (from Product p in _cache  
        where p.Id == id  
        select p).SingleOrDefault();  
    }

    private Product _getByProduct(ISession session, Product product)
    {
      return session.CreateCriteria(typeof(Product))
        .Add(Expression.Eq("Id", product.Id))
        .Add(Expression.Eq("Name", product.Name))
        .Add(Expression.Eq("Price", product.Price))
        .Add(Expression.Eq("Description", product.Description))
        .UniqueResult<Product>();
    }
  }
}

[TestDataHelper.cs]
using System;
using NHibernate;
using NHibernate.Cfg;

using NHibernateExample;

namespace NHibernateExample.TestData
{
  public class TestDataHelper
  {
    private static ISessionFactory _factory;

    private static ISessionFactory Factory
    {
      get
      {
        if (_factory == null)
        {
          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");
          _factory = cfg.BuildSessionFactory();
        }
        return _factory;
      }
    }

    public static ISession OpenSession()
    {
      return Factory.OpenSession();
    }
  }
}
ライブラリとしてビルドします。

[ビルド実行例]
$ cd ~/src/cs/NHibernateExample
$ gmcs -t:library -r:NHibernate.dll -out:./Test/NHibernateExample.dll Product.cs IProductRepository.cs -recurse:./Driver/*.cs -recurse:./TestData/*.cs
動作確認用プログラム
ProductRepositoryインスタンスを使用したDB操作を行います(「db4o編」で使用したのと同様のものです)。

[client.cs]
using System;

using NHibernateExample;
using NHibernateExample.TestData;

namespace NHibernateExample.Test
{
  // 「db4o編」と同様
}
/*
* ビルド:
*
*   gmcs -r:NHibernateExample.dll client.cs
*
* 実行:
*
*   mono client.exe
*
*/

[実行例]
$ cd ~/src/cs/NHibernateExample/Test
$ mono client.exe
Connect to
1:SQLite
2:PostgreSQL
3:MySQL
4:SQLServer
5:Oracle
6:Firebird
7:DB2
?> 1
ID:0 NAME:SQLite 3 PRICE: DESCRIPTION:SQLite 3.6.10
ID:1 NAME:Clamp PRICE:12.48 DESCRIPTION:Workbench clamp
ID:50 NAME:Flat Head Screwdriver PRICE:3.17 DESCRIPTION:Flat head
ID:75 NAME:Tire Bar PRICE: DESCRIPTION:Tool for changing tires.
ID:3000 NAME:3mm Bracket PRICE:0.52 DESCRIPTION:

1:ADD
2:UPDATE
3:REMOVE
4:RELOAD
5:EXIT
?> 1
...

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

0 件のコメント:

コメントを投稿