検索処理(BeanList)

 さっそく複数件のobjectを検索してみましょう。検索するためにはBasicSelectHandlerを使います。 次のようなプロパティが用意されています。

Seasar.Extension.ADO.Impl.BasicSelectHandler

プロパティ説明S2Containerでの設定例
DataSourceDataSource通常自動的に設定されます。
Sql実行したいSQL文"SELECT * FROM emp"
DataReaderHandlerSystem.Data.IDataReaderを処理するHandlerのクラス 複数件のobjectを返すためにはBeanListDataReaderHandlerを使います。
※.NET 2.0のGenericを使用する場合、BeanGenericListDataReaderHandlerを使います。
<component
  class="Seasar.Extension.ADO.
Impl.BeanListDataReaderHandler">

  <arg>Seasar.Examples.Reference.
ADO.Employee</arg>

</component>
CommandTimeout コマンドが実行されるまでの待機時間(秒)。値が-1の場合は特に設定しない (System.Data.IDbCommand.
CommandTimeoutプロパティの規定値が適用)。

Seasar.Examples.Reference.ADO.SelectBeanList.dicon

<components>
  <include path="Seasar.Examples/Ado.dicon" />
  <component name="SelectBeanListClient"
class="Seasar.Examples.Reference.ADO.SelectBeanListClient"/>

  <component name="SelectBeanListHandler"
class="Seasar.Extension.ADO.Impl.BasicSelectHandler">
    <property name="Sql">
"SELECT empno, ename, job, mgr, hiredate, sal, comm, deptno FROM emp" </property> <property name="DataReaderHandler"> <component class="Seasar.Extension.ADO.Impl.BeanListDataReaderHandler"> <arg>Seasar.Examples.Reference.ADO.Employee</arg> </component> </property> </component> </components>

Seasar.Examples.Reference.ADO.SelectBeanListClient

C#

using System;
using System.Collections;
using Seasar.Extension.ADO;
using Seasar.Framework.Container;
using Seasar.Framework.Container.Factory;

namespace Seasar.Examples.Reference.ADO
{
    public class SelectBeanListClient
    {
        private const string
            PATH = "Seasar.Examples/Reference/ADO/SelectBeanList.dicon";

        public void Main()
        {
            IS2Container container = S2ContainerFactory.Create(PATH);
            container.Init();
            try
            {
                ISelectHandler handler = (ISelectHandler)
                    container.GetComponent("SelectBeanListHandler");
                IList result = (IList) handler.Execute(null);
                for (int i = 0; i < result.Count; ++i)
                {
                    Console.Out.WriteLine(result[i]);
                }
            }
            finally
            {
                container.Destroy();
            }
        }
    }
}

実行結果

DEBUG 2006-06-19 23:26:59,890 [9] 論理的なコネクションを取得しました
DEBUG 2006-06-19 23:26:59,984 [9] 論理的なコネクションを閉じました
7369, SMITH, CLERK, 7902, 1980/12/17 0:00:00, 800, , 20, 
7499, ALLEN, SALESMAN, 7698, 1981/02/20 0:00:00, 1600, 300, 30, 
7521, WARD, SALESMAN, 7698, 1981/02/22 0:00:00, 1250, 500, 30, 
7566, JONES, MANAGER, 7839, 1981/04/02 0:00:00, 2975, , 20, 
7654, MARTIN, SALESMAN, 7698, 1981/09/28 0:00:00, 1250, 1400, 30, 
7698, BLAKE, MANAGER, 7839, 1981/05/01 0:00:00, 2850, , 30, 
7782, CLARK, MANAGER, 7839, 1981/06/09 0:00:00, 2450, , 10, 
7788, SCOTT, ANALYST, 7566, 1982/12/09 0:00:00, 3000, , 20, 
7839, KING, PRESIDENT, , 1981/11/17 0:00:00, 5000, , 10, 
7844, TURNER, SALESMAN, 7698, 1981/09/08 0:00:00, 1500, 0, 30, 
7876, ADAMS, CLERK, 7788, 1983/01/12 0:00:00, 1100, , 20, 
7900, JAMES, CLERK, 7698, 1981/12/03 0:00:00, 950, , 30, 
7902, FORD, ANALYST, 7566, 1981/12/03 0:00:00, 3000, , 20, 
7934, MILLER, CLERK, 7782, 1982/01/23 0:00:00, 1300, , 10, 

検索処理(Bean)

 1件のobjectを検索するためには上記と同様にBasicSelectHandlerを使います。 BeanDataReaderHandlerを使うこと以外は上記と同様です。結果はリストではなくobjectとしてかえってきます。

Seasar.Examples.Reference.ADO.SelectBean.dicon

<components>
  <include path="Seasar.Examples/Ado.dicon" />
  <component name="SelectBeanClient"
      class="Seasar.Examples.Reference.ADO.SelectBeanClient"/>
  <component name="SelectBeanHandler"
      class="Seasar.Extension.ADO.Impl.BasicSelectHandler">
    <property name="Sql">
"SELECT empno, ename, job, mgr, hiredate, sal, comm,
deptno FROM emp WHERE empno = @empno"</property> <property name="DataReaderHandler"> <component class="Seasar.Extension.ADO.Impl.BeanDataReaderHandler"> <arg>Seasar.Examples.Reference.ADO.Employee</arg> </component> </property> </component> </components>

Seasar.Examples.Reference.ADO.SelectBeanClient

C#

using System;
using Seasar.Extension.ADO;
using Seasar.Framework.Container;
using Seasar.Framework.Container.Factory;

namespace Seasar.Examples.Reference.ADO
{
    public class SelectBeanClient
    {
        private const string PATH = 
            "Seasar.Examples/Reference/ADO/SelectBean.dicon";

        public void Main()
        {
            IS2Container container = S2ContainerFactory.Create(PATH);
            container.Init();
            try
            {
                ISelectHandler handler = (ISelectHandler)
                    container.GetComponent("SelectBeanHandler");
                Employee result = (Employee)
                    handler.Execute(new object[] { 7788 });
                Console.Out.WriteLine(result);
            }
            finally
            {
                container.Destroy();
            }
        }
    }
}

実行結果

DEBUG 2006-06-19 23:34:54,234 [9] 論理的なコネクションを取得しました
DEBUG 2006-06-19 23:34:54,249 [9] 論理的なコネクションを閉じました
7788, SCOTT, ANALYST, 7566, 1982/12/09 0:00:00, 3000, , 20, 

検索処理(DictionaryList)

 複数件のDictionaryを取得することもできます。DataReaderHandlerにはDictionaryListDataReaderHandlerを使います。

Seasar.Examples.Reference.ADO.SelectDictionaryList.dicon

<components>
  <include path="Seasar.Examples/Ado.dicon" />
  <component name="SelectDictionaryListClient" 
class="Seasar.Examples.Reference.ADO.SelectDictionaryListClient"/> <component name="SelectDictionaryListHandler"
class="Seasar.Extension.ADO.Impl.BasicSelectHandler"> <property name="Sql">
"SELECT empno, ename, job, mgr, hiredate, sal, comm, deptno FROM emp" </property> <property name="DataReaderHandler"> <component class="Seasar.Extension.ADO.Impl.DictionaryListDataReaderHandler"/> </property> </component> </components>

Seasar.Examples.Reference.ADO.SelectDictionaryListClient

C#

using System;
using System.Collections;
using Seasar.Extension.ADO;
using Seasar.Framework.Container;
using Seasar.Framework.Container.Factory;

namespace Seasar.Examples.Reference.ADO
{
    public class SelectDictionaryListClient
    {
        private const string
            PATH = "Seasar.Examples/Reference/ADO/SelectDictionaryList.dicon";

        public void Main()
        {
            IS2Container container = S2ContainerFactory.Create(PATH);
            container.Init();
            try
            {
                ISelectHandler handler = (ISelectHandler)
                    container.GetComponent("SelectDictionaryListHandler");
                IList result = (IList) handler.Execute(null);
                for (int i = 0; i < result.Count; ++i)
                {
                    Console.Out.WriteLine(DictionaryUtil.ToDecorateString(
                        (IDictionary) result[i]));
                }
            }
            finally
            {
                container.Destroy();
            }
        }
    }
}

実行結果

DEBUG 2006-06-19 23:43:24,749 [9] 論理的なコネクションを取得しました
DEBUG 2006-06-19 23:43:24,765 [9] 論理的なコネクションを閉じました
ename=SMITH, hiredate=1980/12/17 0:00:00, comm=null, deptno=20, 
 job=CLERK, empno=7369, sal=800.00, mgr=7902
ename=ALLEN, hiredate=1981/02/20 0:00:00, comm=300.00, deptno=30,
 job=SALESMAN, empno=7499, sal=1600.00, mgr=7698
ename=WARD, hiredate=1981/02/22 0:00:00, comm=500.00, deptno=30,
 job=SALESMAN, empno=7521, sal=1250.00, mgr=7698
ename=JONES, hiredate=1981/04/02 0:00:00, comm=null, deptno=20, 
 job=MANAGER, empno=7566, sal=2975.00, mgr=7839
ename=MARTIN, hiredate=1981/09/28 0:00:00, comm=1400.00, deptno=30,
 job=SALESMAN, empno=7654, sal=1250.00, mgr=7698
ename=BLAKE, hiredate=1981/05/01 0:00:00, comm=null, deptno=30,
 job=MANAGER, empno=7698, sal=2850.00, mgr=7839
ename=CLARK, hiredate=1981/06/09 0:00:00, comm=null, deptno=10,
 job=MANAGER, empno=7782, sal=2450.00, mgr=7839
ename=SCOTT, hiredate=1982/12/09 0:00:00, comm=null, deptno=20,
 job=ANALYST, empno=7788, sal=3000.00, mgr=7566
ename=KING, hiredate=1981/11/17 0:00:00, comm=null, deptno=10,
 job=PRESIDENT, empno=7839, sal=5000.00, mgr=null
ename=TURNER, hiredate=1981/09/08 0:00:00, comm=0.00, deptno=30,
 job=SALESMAN, empno=7844, sal=1500.00, mgr=7698
ename=ADAMS, hiredate=1983/01/12 0:00:00, comm=null, deptno=20,
 job=CLERK, empno=7876, sal=1100.00, mgr=7788
ename=JAMES, hiredate=1981/12/03 0:00:00, comm=null, deptno=30,
 job=CLERK, empno=7900, sal=950.00, mgr=7698
ename=FORD, hiredate=1981/12/03 0:00:00, comm=null, deptno=20,
 job=ANALYST, empno=7902, sal=3000.00, mgr=7566
ename=MILLER, hiredate=1982/01/23 0:00:00, comm=null, deptno=10,
 job=CLERK, empno=7934, sal=1300.00, mgr=7782

検索処理(Dictionary)

 1件のDictionaryを取得することもできます。DataReaderHandlerにはDictionaryDataReaderHandlerを使います。

Seasar.Examples.Reference.ADO.SelectDictionary.dicon

<components>
  <include path="Seasar.Examples/Ado.dicon" />
  <component name="SelectDictionaryClient"
      class="Seasar.Examples.Reference.ADO.SelectDictionaryClient"/>
  <component name="SelectDictionaryHandler"
      class="Seasar.Extension.ADO.Impl.BasicSelectHandler">
    <property name="Sql">
"SELECT empno, ename, job, mgr, hiredate, sal, comm, deptno
FROM emp WHERE empno = @empno"</property> <property name="DataReaderHandler"> <component class="Seasar.Extension.ADO.Impl.DictionaryDataReaderHandler"/> </property> </component> </components>

Seasar.Examples.Reference.ADO.SelectDictionaryClient

C#

using System;
using System.Collections;
using Seasar.Extension.ADO;
using Seasar.Framework.Container;
using Seasar.Framework.Container.Factory;

namespace Seasar.Examples.Reference.ADO
{
    public class SelectDictionaryClient
    {
        private const string PATH =
            "Seasar.Examples/Reference/ADO/SelectDictionary.dicon";

        public void Main()
        {
            IS2Container container = S2ContainerFactory.Create(PATH);
            container.Init();
            try
            {
                ISelectHandler handler = (ISelectHandler)
                    container.GetComponent("SelectDictionaryHandler");
                IDictionary result = (IDictionary)
                    handler.Execute(new object[] { 7788 });
                Console.Out.WriteLine(DictionaryUtil.ToDecorateString(result));
            }
            finally
            {
                container.Destroy();
            }
        }
    }
}

実行結果

DEBUG 2006-06-19 23:46:25,640 [9] 論理的なコネクションを取得しました
DEBUG 2006-06-19 23:46:25,656 [9] 論理的なコネクションを閉じました
ename=SCOTT, hiredate=1982/12/09 0:00:00, comm=null, deptno=20,
 job=ANALYST, empno=7788, sal=3000.00, mgr=7566

更新処理

 更新するためにはBasicUpdateHandlerを使います。次のようなプロパティが用意されています。

Seasar.Extension.ADO.Impl.BasicUpdateHandler

プロパティ説明S2Containerでの設定例
DataSourceDataSource通常自動的に設定されます。
Sql実行したSQL文"UPDATE emp SET ename = @ename WHERE empno = @empno "

Seasar.Examples.Reference.ADO.Update.dicon

<components>
  <include path="Seasar.Examples/Ado.dicon" />
  <component name="UpdateClient"
      class="Seasar.Examples.Reference.ADO.UpdateClient"/>
  <component name="UpdateHandler"
     class="Seasar.Extension.ADO.Impl.BasicUpdateHandler">
    <property name="Sql">
        "UPDATE emp SET ename = @ename WHERE empno = @empno"
    </property>
  </component>
</components>

Seasar.Examples.Reference.ADO.UpdateClient

C#

using System;
using Seasar.Extension.ADO;
using Seasar.Framework.Container;
using Seasar.Framework.Container.Factory;

namespace Seasar.Examples.Reference.ADO
{
    public class UpdateClient
    {
        private const string PATH =
            "Seasar.Examples/Reference/ADO/Update.dicon";

        public void Main()
        {
            IS2Container container = S2ContainerFactory.Create(PATH);
            container.Init();
            try
            {
                IUpdateHandler handler = (IUpdateHandler)
                    container.GetComponent("UpdateHandler");
                int result = (int) handler.Execute(
                    new object[] { "SCOTT", 7788 });
                Console.Out.WriteLine(result);
            }
            finally
            {
                container.Destroy();
            }
        }
    }
}

実行結果

DEBUG 2006-06-19 23:55:46,999 [9] 論理的なコネクションを取得しました
DEBUG 2006-06-19 23:55:47,031 [9] 論理的なコネクションを閉じました
1

 NET Framework型とデータベースの列を対応させる場合、列にNULL値が格納されていると例外が発生する場合があります。 .NET Framework型がSystem.Int32等の構造体の場合、NULLを表現できないからです。

 列にNULL値が格納される場合、 以下の2つの方法を使用します。

 データベースのデータ型と各方法の対応を次の表に示します。

System.Data.DbType.NET Framework型NullablesSystem.Data.SqlTypesSystem.Nullable
BooleanBooleanNullableBooleanSqlBooleanNullable<Boolean>
ByteByteNullableByteSqlByteNullable<Byte>
BinaryByte[]NullableByteSqlBinaryNullable<Byte>
DateTimeDateTimeNullableDateTimeSqlDateTimeNullable<DateTime>
DecimalDecimalNullableDecimalSqlDecimalNullable<Decimal>
DoubleDoubleNullableDoubleSqlDoubleNullable<Double>
SingleSingleNullableSingleSqlSingleNullable<Single>
GuidGuidNullableGuidSqlGuidNullable<Guid>
Int16Int16NullableInt16SqlInt16Nullable<Int16>
Int32Int32NullableInt32SqlInt32Nullable<Int32>
Int64Int64NullableInt64SqlInt64Nullable<Int64>
StringString-SqlString-
TimeTimeSpan--Nullable<TimeSpan>
SByteSByteNullableSByte-Nullable<SByte>

NHibernateContribのNullables(バージョン1.3.7から廃止)

 NHibernateContribのNullablesを利用する場合、以下のファイル(アセンブリ)への参照を追加する必要があります。

  • s2container.net/lib/Nullables.dll

 ソースファイルからは、次のように使用します。

  • Nullables名前空間をインポートする必要があります。
  • NULLであるか確認する場合、HasValueプロパティを使用します。
  • 値を取り出す場合、Valueプロパティを使用します。

C#

using System.Text;
using Nullables;

namespace Foo
{
    public class Bar
    {
        private NullableInt64 id;

        public NullableInt64 Id
        {
            get { return id; }
            set { id = value; }
        }

        private NullableBoolean boolType;

        public NullableBoolean BoolType
        {
            get { return boolType; }
            set { boolType = value; }
        }

        public override string ToString()
        {
            StringBuilder buf = new StringBuilder();
            buf.Append(id.HasValue ?
                id.Value.ToString() : "NULL").Append(", ");
            buf.Append(boolType.HasValue ?
                boolType.Value.ToString() : "NULL").Append(", ");
            return buf.ToString();
        }
    }
}

System.Data.SqlTypesのNull

 ソースファイルからは、次のように使用します。

  • System.Data.SqlTypes名前空間をインポートする必要があります。
  • NULLであるか確認する場合、IsNullプロパティを使用します。
  • 値を取り出す場合、Valueプロパティを使用します。

C#

using System.Data.SqlTypes;
using System.Text;

namespace Foo
{
    public class Bar
    {
        private SqlInt64 id;

        public SqlInt64 Id
        {
            get { return id; }
            set { id = value; }
        }

        private SqlBoolean boolType;

        public SqlBoolean BoolType
        {
            get { return boolType; }
            set { boolType = value; }
        }

        public override string ToString()
        {
            StringBuilder buf = new StringBuilder();
            buf.Append(!id.IsNull ?
                id.Value.ToString() : "NULL").Append(", ");
            buf.Append(!boolType.IsNull ?
                boolType.Value.ToString() : "NULL").Append(", ");
            return buf.ToString();
        }
    }
}

System.Nullable(.NET 2.0以降)

 ソースファイルからは、次のように使用します。

  • System名前空間をインポートする必要があります。
  • NULLであるか確認する場合、HasValueプロパティを使用します。
  • 値を取り出す場合、Valueプロパティを使用します。

C#

using System;
using System.Text;

namespace Foo
{
    public class Bar
    {
        private Nullable<Int64> id;

        public Nullable<Int64> Id
        {
            get { return id; }
            set { id = value; }
        }

        private Nullable<Boolean> boolType;

        public Nullable<Boolean> BoolType
        {
            get { return boolType; }
            set { boolType = value; }
        }

        public override string ToString()
        {
            StringBuilder buf = new StringBuilder();
            buf.Append(id.HasValue ? 
                id.Value.ToString() : "NULL").Append(", ");
            buf.Append(boolType.HasValue ? 
                boolType.Value.ToString() : "NULL").Append(", ");
            return buf.ToString();
        }
    }
}

 SQL文に埋め込むパラメータマーカーは、ADO.NETのデータプロパイダによって異なります。 (SqlClientは"@parmname"、OracleClientは":parmname"、OleDbは、"?"、Odbcは、"?")

 S2ADOではデータプロパイダごとにパラメータマーカーを自動的に切り替えるため、 データプロパイダに依存しないSQL文の作成を可能にしています。

 例えば、次のようになります。

データプロバイダSQL文
(ユーザが記述したSQL文)SELECT * FROM emp WHERE empno = @empno OR empno = :empno OR empno = ?
SqlClientSELECT * FROM emp WHERE empno = @0 OR empno = @1 OR empno = @2
OracleClientSELECT * FROM emp WHERE empno = :0 OR empno = :1 OR empno = :2
OleDbSELECT * FROM emp WHERE empno = ? OR empno = ? OR empno = ?
OdbcSELECT * FROM emp WHERE empno = ? OR empno = ? OR empno = ?

 ※SQL文に複数のパラメータマーカーを混在することは可能ですが、可読性の点から単一のパラメータマーカーを使用してください。

 Oracle Data Provider .NET(ODP.NET)は、Unicodeのマッピングに一部問題があり、 ~が化けてしまいます。この問題に対処するには、Ado.diconにOracleDataReaderFactoryの設定を追加します。

<components namespace="Ado">
  ....
  <component class="Seasar.Extension.ADO.Impl.OracleDataReaderFactory" />
</components>

 Oracleのようにbool型に対応していないRDBMSもあります。 この問題に対処するには、Ado.diconにBooleanToIntCommandFactoryの設定を追加します。

<components namespace="Ado">
  ....
  <component class="Seasar.Extension.ADO.Impl.BooleanToIntCommandFactory" />
</components>