連載
Enterprise Library概説

洗練されたデータアクセス機能を実装しよう

市川 龍太(patterns & practices Champion
2005/07/16
Page1 Page2 Page3 Page4

Data Access Application Blockを使うメリット

 次のサンプル・プログラムは、EntLibQuickStartsデータベースのCustomersテーブルから全レコードを取得するメソッドを、DAABを使用せずに従来のADO.NETによる方法で実装したサンプル・プログラムである。

using System.Data.SqlClient;

public class CustomersTableDataGateway
{
  public static DataSet GetCustomers()
  {
    string query = "SELECT * FROM Customers";
    using( SqlConnection connection =
      new SqlConnection("接続文字列") )
    {
      SqlDataAdapter adapter =
        new SqlDataAdapter(query, connection);
      DataSet ds = new DataSet();
      adapter.Fill(ds, "Customers");
    }
    return ds;
  }
}
Data Access Application Blockを使用しない場合のサンプル・プログラム

 これをDAABを使用して実装すると、以下のサンプル・プログラムになる。

using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Data.Sql;

public class CustomersTableDataGateway
{
  public DataSet GetCustomers()
  {
    Database database = DatabaseFactory.CreateDatabase();
    string query = "SELECT * FROM Customers";
    DBCommandWrapper wrapper =
      database.GetSqlStringCommandWrapper(query);
    return database.ExecuteDataSet(wrapper);
  }
}
Data Access Application Blockを使用した場合のサンプル・プログラム
このサンプル・プログラムを実行するには、以下の2つのアセンブリを参照設定に追加する必要がある。
 ・microsoft.practices.enterpriselibrary.configuration
 ・microsoft.practices.enterpriselibrary.data

 以上の2つのサンプル・プログラムを比較することから、次の3つのメリットを取り挙げることができる。

  1. データソースへの接続情報の隠ぺい
  2. シンプルなインターフェイスによるコード記述量の削減
  3. データソースの抽象化

 これらのメリットについて、以下で詳しく説明していこう。

1. データソースへの接続情報の隠ぺい

 DAABを使用したサンプル・プログラムでは、SQL Sererに接続するための接続情報(接続文字列)をどこにも記述していない。これは、DatabaseFactoryクラスのCreateDatabaseメソッドを呼び出した時点で、アプリケーション構成ファイル(=先ほどConfigurationコンソールで出力したファイル)の構成情報を読み込んでいるためである。この処理は、DAABと依存関係にあるConfiguration Application Blockが構成情報をデシリアライズ(=XML形式の構成情報から対応するオブジェクトを復元する処理)することにより実現されている。

 また、DAABを使用した場合は、(サンプル・プログラムを見れば分かるように)SqlConnectionクラスを明示的にインスタンス化する必要がない。その結果としてDAABを使用する側が、接続リソースを解放する必要もなくなるのである。

2. シンプルなインターフェイスによるコード記述量の削減

 上の2つのサンプル・プログラムを比べると、DAABを使用した場合はコード記述量が削減されていることがお分かりいただけると思うが、これはストアドプロシージャを呼び出すコードになるとさらに顕著になって現れる。

 以下のコードは、ストアドプロシージャを呼び出すサンプル・プログラムを、ADO.NETのみで記述した例である。

using System.Data.SqlClient;

public class CustomersTableDataGateway
{
  public static void GetProductDetails(int productID, ref string productName, ref decimal unitPrice)
  {
    using( SqlConnection connection =
      new SqlConnection(connectionString) )
    {
      connection.Open();
      SqlCommand command  = connection.CreateCommand();
      command.CommandType = CommandType.StoredProcedure;
      command.CommandText = "GetCustmerDetails";

      command.Parameters.Add("@CustomerID ", SqlDbType.Int);
      command.Parameters["@CustomerID"].Direction =
        ParameterDirection.Input;
      command.Parameters["@CompanyName"].Value = custmerID;

      command.Parameters.Add("@ProductName", SqlDbType.VarChar, 50);
      command.Parameters["@ProductName"].Direction =
        ParameterDirection.Output;

      command.Parameters.Add("@UnitPrice", SqlDbType.Money);
      command.Parameters["@UnitPrice"].Direction =
        ParameterDirection.Output;

      rowCount = command.ExecuteNonQuery();
      custmerID = command.Parameters["@ProductName"].Value
      companyName = command.Parameters["@UnitPrice"].Value
    }
  }
}
Data Access Appllication Blockを使用しない場合のストアドプロシージャを呼び出すサンプル・プログラム
ここで呼び出しているGetCustmerDetailsストアドプロシージャは、SetUpQuickStartsDB.batファイルを実行したときに、EntLibQuickStartsデータベース上に作成される。

 そして、次がDAABを使用した場合のストアドプロシージャを呼び出すサンプル・プログラムである。

using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Data.Sql;

public class CustomersTableDataGateway
{
  public static void GetProductDetails(int productID, ref string productName, ref decimal unitPrice)
  {
    DBCommandWrapper dbCommandWrapper =
      db.GetStoredProcCommandWrapper("GetProductDetails");
    dbCommandWrapper.AddInParameter("@ProductID", DbType.Int32, 1);
    dbCommandWrapper.AddOutParameter(
      "@ProductName", DbType.String, 50);
    dbCommandWrapper.AddOutParameter(
      "@UnitPrice", DbType.Currency, int.MaxValue);

    db.ExecuteNonQuery(dbCommandWrapper);
    productName =
      dbCommandWrapper.GetParameterValue("@ProductName");
    unitPrice = dbCommandWrapper.GetParameterValue("@UnitPrice");
  }
}
Data Access Appllication Blockを使用した場合のストアドプロシージャを呼び出すサンプル・プログラム

 DAABを使用した方のサンプル・プログラムでは、SqlCommandクラスのインスタンス化と各プロパティ(CommandTypeプロパティ、CommnadTextプロパティ)の設定が不要になり、DBCommandWrapperクラスをインスタンス化するだけで済んでしまうのである。

 ほかにもストアドプロシージャに渡すパラメータの設定が、DBCommandWrapperオブジェクトのAddInParameterメソッドやAddOutParameterメソッドを使うことで、シンプルになっていることがお分かりかと思う。

3. データソースの抽象化

 ところで、データソースとなるDBMSをSQL ServerからOracleに変更する場合、上記のサンプル・プログラムのソース・コードはどうなるだろうか?

 DAABを使用していない場合だと、いままでSQL Serverデータ・プロバイダ(System.Data.SqlClient名前空間以下のクラス。例えば、先ほどのSqlCommandクラスなど)を使って実装していたコードを、すべてOracleデータ・プロバイダ(System.Data.OracleClient名前空間以下のクラス。例えば、OracleCommandクラスなど)に修正しなければならなくなるだろう。

 しかしDAABを使用していた場合であれば、Configurationコンソールで「Database Types」ノードのType Nameプロパティを、

Microsoft.Practices.EnterpriseLibrary.Data.Sql.SqlDatabase, Microsoft.Practices.EnterpriseLibrary.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

から、

Microsoft.Practices.EnterpriseLibrary.Data.Oracle.OracleDatabase, Microsoft.Practices.EnterpriseLibrary.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

に変更するだけでよい。

 DAABでは、抽象化により接続先データベースに依存するようなコードの記述を完全に排除しているため、ソース・コードを修正する必要がないのである。

 なお、このデータソースの抽象化については、インターフェイス(IDbConnectionインターフェイスやIDbCommnadインターフェイスなど)を使って実装すればよいのではないか? という意見があるかもしれない。しかしインターフェイスを使って実装する場合には、以下の問題点があることを留意しておかなければならない。

  • IDCommandインターフェイスには、ExecuteXmlReaderメソッドが存在しない(このメソッドはSqlCommandクラスでは実装されている)

  • インターフェイス用の、SqlExceptionクラス(System.Data.SqlClient名前空間)やOleDbExceptionクラス(System.Data.OleDb名前空間)のような例外クラスが存在しない

  • SqlDbType列挙体(System.Data名前空間)のようなデータ・プロバイダ固有のデータ型が存在しない

 データ型に関しては「OleDbデータ・プロバイダを使えばよい」という意見もあるかもしれないが、これはパフォーマンスの点でSQL Serverデータ・プロバイダやOracleデータ・プロバイダに劣ることから、やはりDAABを使うことが最適な選択肢といえるだろう。

 Enterprise Library 1.0のリリース以後、すでに多くのDAAB用の拡張機能やツールが公開されている。そのいくつかを最後に紹介しておく。


 INDEX
  連載:Enterprise Library概説
  洗練されたデータアクセス機能を実装しよう
    1.Data Access Application Blockとは何か?
    2.ConfigurationコンソールでData Access Application Blockの構成を設定する
  3.Data Access Application Blockを使うメリット
    4.Data Access Application Blockをさらに使いやすくするツールたち
 
インデックス・ページヘ  「Enterprise Library概説」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間