[C#] 使用模版方法統一操作行為

  • 7352
  • 0
  • 2009-10-22

【C#】使用模版方法統一操作行為

在專案開發時,我們通常會對資料庫進行操作,

在平時若我們需要一組特定的資料(Data Model),就會建立一個Function來進行撈取資料,是十分合理的。

但隨著專案越來越大,若要專案中的每位成員都使用相同的流程操作,甚至是統一錯誤的Exception時,可就是一項大工程了!

這個時候我們就可以使用模版方法(Template),不但可以統一操作資料庫的邏輯,更可以增加日後維護的方便性,

只需修改一個地方,即可套用到所有的成員。

 

首先我們建立一個DBHelper的Class,注意此處都是使用DB的基礎抽象成員(DbConnection,DbCommand...etc),

我們只需要依照自己所需使用的DB類型來傳入正確的類別即可 (如OracleConnection)

在這次例子中,僅僅實作了兩組模版方法ExecuteReaderTemplate及ExecuteNonReaderTemplate,

分別為使用DataReader讀取資料,以及不使用DataReader的模板


using System;
using System.Diagnostics;
using System.Data.Common;

public static class DBHelper
{
    public static TResult ExcuteReaderTemplate<TResult>
        (Func<DbConnection> connectionSetting, Func<DbCommand> commandSetting, Func<DbDataReader, TResult> dataMapping)
    {
        DbConnection connection = connectionSetting();

        try
        {
            connection.Open();
        }
        catch (Exception error)
        {
            Debug.WriteLine(string.Format("Connection Open Error : {0}", error.Message));
            Debug.WriteLine(error.StackTrace);
            return default(TResult);
        }

        DbCommand command = commandSetting();
        command.Connection = connection;

        DbDataReader reader;

        try
        {
            reader = command.ExecuteReader();
        }
        catch (Exception error)
        {
            Debug.WriteLine(string.Format("Execute Reader Error : {0}", error.Message));
            Debug.WriteLine(error.StackTrace);
            return default(TResult);
        }        
        

        try
        {
            TResult data;

            data = dataMapping(reader);

            return data;
        }
        catch (Exception error)
        {
            Debug.WriteLine(string.Format("Data Mapping Error : {0}", error.Message));
            Debug.WriteLine(error.StackTrace);
            return default(TResult);
        }
        finally
        {
            connection.Close();
        }
    }

    public static void ExcuteNonReaderTemplate
        (Func<DbConnection> connectionSetting, Func<DbCommand> commandSetting)
    {
        DbConnection connection = connectionSetting();

        try
        {
            connection.Open();
        }
        catch (Exception error)
        {
            Debug.WriteLine(string.Format("Connection Open Error : {0}", error.Message));
            Debug.WriteLine(error.StackTrace);
        }

        DbCommand command = commandSetting();
        command.Connection = connection;        

        try
        {
            command.ExecuteNonQuery();
        }
        catch (Exception error)
        {
            Debug.WriteLine(string.Format("Execute Command Error : {0}", error.Message));
            Debug.WriteLine(error.StackTrace);            
        }
        finally
        {
            connection.Close();
        }       
    }
}

建立好模板方法方法之後,我們可以輕易的將其套用在資料庫連接類別之中,範例如下

(此處使用Oracle做為範例)

 


using System;
using System.Collections.Generic;
using System.Text;
using System.Data.OracleClient;

public class Data
{
    public int ID { get; set; }
    public string Name { get; set; }
}

public class DbAccessObj
{
    public static Data GetUserById(int id)
    {
        return DBHelper.ExcuteReaderTemplate<Data>(
                   connectionSetting,
                   () =>
                   {
                       string commandString = "SELECT * FROM MyTable WHERE ID = " + id;
                       return new OracleCommand(commandString);
                   },
                   (reader) =>
                   {
                       reader.Read();

                       Data tmpData = new Data();
                       tmpData.ID = reader.GetInt16(0);
                       tmpData.Name = reader.GetString(1);

                       return tmpData;
                   }
               );
    }

    private static OracleConnection connectionSetting()
    {
        string connectionString = "Data Source=MyServer;User ID=MyName;Password=MyPassword;Unicode=True";
        return new OracleConnection(connectionString);
    }
}

是不是輕鬆又愉快呢?

模板方法還可以應用在許多地方,可以方便且快速的統一操作行為,未來有機會再跟大家分享囉