SQLは自由に発行したい。でもADO.NETを使うのはめんどくさい。そんなあなたのために用意されているのが、S2ADOです。
SQLは自由に発行したい。でもADO.NETを使うのはめんどくさい。そんなあなたのために用意されているのが、S2ADOです。
さっそく複数件のobjectを検索してみましょう。検索するためにはBasicSelectHandlerを使います。 次のようなプロパティが用意されています。
プロパティ | 説明 | S2Containerでの設定例 |
---|---|---|
DataSource | DataSource | 通常自動的に設定されます。 |
Sql | 実行したいSQL文 | "SELECT * FROM emp" |
DataReaderHandler | System.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プロパティの規定値が適用)。 |
<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>
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,
1件のobjectを検索するためには上記と同様にBasicSelectHandlerを使います。 BeanDataReaderHandlerを使うこと以外は上記と同様です。結果はリストではなくobjectとしてかえってきます。
<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>
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,
複数件のDictionaryを取得することもできます。DataReaderHandlerにはDictionaryListDataReaderHandlerを使います。
<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>
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
1件のDictionaryを取得することもできます。DataReaderHandlerにはDictionaryDataReaderHandlerを使います。
<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>
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を使います。次のようなプロパティが用意されています。
プロパティ | 説明 | S2Containerでの設定例 |
---|---|---|
DataSource | DataSource | 通常自動的に設定されます。 |
Sql | 実行したSQL文 | "UPDATE emp SET ename = @ename WHERE empno = @empno " |
<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>
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型 | Nullables | System.Data.SqlTypes | System.Nullable |
---|---|---|---|---|
Boolean | Boolean | NullableBoolean | SqlBoolean | Nullable<Boolean> |
Byte | Byte | NullableByte | SqlByte | Nullable<Byte> |
Binary | Byte[] | NullableByte | SqlBinary | Nullable<Byte> |
DateTime | DateTime | NullableDateTime | SqlDateTime | Nullable<DateTime> |
Decimal | Decimal | NullableDecimal | SqlDecimal | Nullable<Decimal> |
Double | Double | NullableDouble | SqlDouble | Nullable<Double> |
Single | Single | NullableSingle | SqlSingle | Nullable<Single> |
Guid | Guid | NullableGuid | SqlGuid | Nullable<Guid> |
Int16 | Int16 | NullableInt16 | SqlInt16 | Nullable<Int16> |
Int32 | Int32 | NullableInt32 | SqlInt32 | Nullable<Int32> |
Int64 | Int64 | NullableInt64 | SqlInt64 | Nullable<Int64> |
String | String | - | SqlString | - |
Time | TimeSpan | - | - | Nullable<TimeSpan> |
SByte | SByte | NullableSByte | - | Nullable<SByte> |
NHibernateContribのNullablesを利用する場合、以下のファイル(アセンブリ)への参照を追加する必要があります。
ソースファイルからは、次のように使用します。
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(); } } }
ソースファイルからは、次のように使用します。
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(); } } }
ソースファイルからは、次のように使用します。
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 = ? |
SqlClient | SELECT * FROM emp WHERE empno = @0 OR empno = @1 OR empno = @2 |
OracleClient | SELECT * FROM emp WHERE empno = :0 OR empno = :1 OR empno = :2 |
OleDb | SELECT * FROM emp WHERE empno = ? OR empno = ? OR empno = ? |
Odbc | SELECT * 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>