S2Dao.NET を使ってみる

開発環境はこんな感じ

ソース一式をここに置いておく。

DB作成

使用するDBはこんな感じ

CREATE DATABASE [s2daotest]
GO
use [s2daotest]
GO
CREATE TABLE [dbo].[EMP] (
	[EMPNO] numeric (10, 0) NOT NULL ,
	[ENAME] nvarchar (50) NOT NULL ,
	[DEPTNUM] numeric (10, 0) ,
	CONSTRAINT [PK_EMP] PRIMARY KEY CLUSTERED ([EMPNO]))
GO

ソリューション作成

VS2005を起動して、「ファイル」→「新規作成」→「プロジェクト」を選択する。
プロジェクト名を「S2DaoTestApp」としておく。

以下のアセンブリを参照しておく。

エンティティの作成

ファイル名は「Emp.cs」で、ほとんど S2Dao.NET に含まれるサンプル(Employee)と同じ。違うのはこれくらいかな。

  • DEPTNUM に NULL を許可するために System.Data.SqlTypes.SqlDecimal を使用
  • Table属性を省略するためにクラス名を Emp に変更
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlTypes;

namespace S2DaoTestApp {
    public class Emp {
        private int _empno;

        public int EmpNo {
            get { return _empno; }
            set { _empno = value; }
        }

        private string _ename;

        public string Ename {
            get { return _ename; }
            set { _ename = value; }
        }

        private SqlDecimal _deptNum;

        public SqlDecimal DeptNum {
            get { return _deptNum; }
            set { _deptNum = value; }
        }
    }
}

Dao インターフェイスの作成

ファイル名は「IEmpDao.cs」で、EMP テーブルのデータを全件取得するメソッドを定義する。

using System;
using System.Collections.Generic;
using System.Text;
using Seasar.Dao.Attrs;

namespace S2DaoTestApp {
    [Bean(typeof(Emp))]
    public interface IEmpDao {
        Emp[] GetAllList();
    }
}

Ex.dicon ファイル

サンプルからコピーしてきて、プロパティのビルドアクションを「埋め込まれたリソース」にしただけ。ただし、ここを参考に接続文字列を app.config から取得するように変更している。

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
"http://www.seasar.org/dtd/components21.dtd">
<components namespace="Ex">

    <!-- データプロバイダ -->
    <component name="SqlClient" class="Seasar.Extension.ADO.DataProvider">
        <property name="ConnectionType">"System.Data.SqlClient.SqlConnection"</property>
        <property name="CommandType">"System.Data.SqlClient.SqlCommand"</property>
        <property name="ParameterType">"System.Data.SqlClient.SqlParameter"</property>
        <property name="DataAdapterType">"System.Data.SqlClient.SqlDataAdapter"</property>
    </component>
    
    <!-- データソース -->
    <component name="SqlDataSource" class="Seasar.Extension.Tx.Impl.TxDataSource">
        <property name="DataProvider">Ex.SqlClient</property>
        <property name="ConnectionString">appSettings['ConnectionString']</property>
    </component>
    
    <!-- S2Dao.NETのDaoInterceptorとそれに必要なコンポーネント -->
    <component class="Seasar.Extension.ADO.Impl.BasicDataReaderFactory" />
    <component class="Seasar.Extension.ADO.Impl.BasicCommandFactory" />
    <component class="Seasar.Dao.Impl.DaoMetaDataFactoryImpl" />
    <component name="DaoInterceptor"
        class="Seasar.Dao.Interceptors.S2DaoInterceptor"/>
    
    <!-- ローカルトランザクション用のインターセプター -->
    <component name="LocalRequiredTx" class="Seasar.Extension.Tx.TransactionInterceptor">
        <arg><component class="Seasar.Extension.Tx.Impl.LocalRequiredTxHandler" /></arg>
        <property name="TransactionStateHandler">TransactionContext</property>
    </component>
    
    <!-- ローカルトランザクション用のインターセプターで使用します -->
    <component name="TransactionContext" class="Seasar.Extension.Tx.Impl.TransactionContext">
        <property name="IsolationLevel">System.Data.IsolationLevel.ReadCommitted</property>
    </component>
    
    <!-- MSDTC(分散トランザクション)用のインターセプター -->
    <component name="RequiredTx" class="Seasar.Extension.Tx.TransactionInterceptor">
        <arg><component class="Seasar.Extension.Tx.Impl.DTCRequiredTxHandler" /></arg>
        <property name="TransactionStateHandler">DTCTransactionStateHandler</property>
    </component>   
    
    <!-- MSDTC用のインターセプターで使用します -->
    <component name="DTCTransactionStateHandler" class="Seasar.Extension.Tx.Impl.DTCTransactionStateHandler" />
    
</components>

app.dicon ファイル

app.dicon ファイルはこんな感じ。これもビルドアクションを「埋め込まれたリソース」にしておく。C#の場合、リソースを埋め込むとデフォルトの名前空間が追加されるので、Ex.dicon をインクルードする場合は「S2DaoTestApp.Ex.dicon」というように指定しないといけない。

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
"http://www.seasar.org/dtd/components21.dtd">
<components>
  <include path="S2DaoTestApp.Ex.dicon" />

  <component class="S2DaoTestApp.IEmpDao">
    <aspect>Ex.DaoInterceptor</aspect>
  </component>

</components>

アプリケーション構成ファイル

app.config はこんな感じ。
Ex.dicon の時と同じように、configPath は「S2DaoTestApp.app.dicon」とする。
エンティティやDaoを見つけるために、assemblys で S2DaoTestApp を忘れずに参照しておくこと。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="seasar"
       type="Seasar.Framework.Xml.S2SectionHandler, Seasar" />
  </configSections>

  <appSettings>
    <add key="ConnectionString" value="Server=(local);database=s2daotest;Integrated Security=SSPI" />
  </appSettings>
  
  <seasar>
    <configPath>S2DaoTestApp.app.dicon</configPath>
    <assemblys>
      <assembly>Seasar.Dao</assembly>
      <assembly>S2DaoTestApp</assembly>
    </assemblys>
  </seasar>

</configuration>

動作確認

Form1 に Button と DataGridView を追加して、Button がクリックされたら DataGridView に Emp テーブルの内容が表示されるようにしてみた。
DataGridView にはデータソースとして、Emp クラスを選択しておく。

Form1 のコードはこんな感じ。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Seasar.Framework.Container;
using Seasar.Framework.Container.Factory;

namespace S2DaoTestApp {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
            SingletonS2ContainerFactory.Init();
        }

        private void button1_Click(object sender, EventArgs e) {
            try {
                button1.Enabled = false;
                IS2Container c = SingletonS2ContainerFactory.Container;
                IEmpDao dao = (IEmpDao)c.GetComponent(typeof(IEmpDao));
                empBindingSource.DataSource = dao.GetAllList();
            } finally {
                button1.Enabled = true;
            }
        }
    }
}

最終的なソリューションの構成はこんな感じになった。

適当に EMP テーブルにデータを追加しておくとこんな感じに表示される。


SQLADO.NET のコードをまったく書いてないのに、ここまで出来るってやばいですな。
DataSet では扱えない、NULLを許可するフィールドも使えるし。