1. 程式人生 > >自己動手寫ORM框架(二)-AdoHelper支援多資料庫操作的封裝(1)

自己動手寫ORM框架(二)-AdoHelper支援多資料庫操作的封裝(1)

主題:本節主要是底層的針對於資料庫的CRUD,包括對於不同型別資料庫的可擴充套件性。第一步:編寫AdoHelper類,用於封裝對資料庫的操作,能同時支援多個數據庫(目前支援SqlServer、Oracle、Access),可擴充套件支援任何型別的資料庫。

app.config

<?xml version="1.0"?>
<configuration>
<appSettings>
    <add key="dbType" value="oracle"/>
    <add key="connectionString" value
="DataSource=test;UserID=test;Password=123"/>
</appSettings> <system.web> <compilation debug="true"> </compilation> <authentication mode="Windows"/> </system.web> </configuration>

TypeUtils.cs

/// <summary>
/// 物件型別
/// </summary>
public class
TypeUtils { public static object ConvertForType(object value, Type type) { switch (type.FullName) { case "System.String": value = value.ToString(); break; case "System.Boolean": value = bool.Parse(value.ToString()); break
; case "System.Int16": case "System.Int32": case "System.Int64": value = int.Parse(value.ToString()); break; case "System.Double": value = double.Parse(value.ToString()); break; case "System.Decimal": value = new decimal(double.Parse(value.ToString())); break; } return value; } }

CommonUtils.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Reflection;

namespace System.Orm.Common
{
    public class CommonUtils
    {
        /// <summary>  
        /// 用於字串和列舉型別的轉換
        /// </summary>  
        /// <typeparam name="T"></typeparam>  
        /// <param name="value"></param> 
        /// <returns></returns>
        public static T EnumParse<T>(string value)
        {
            try
            {
                return (T)Enum.Parse(typeof(T), value);
            }
            catch
            {
                throw new Exception("傳入的值與列舉值不匹配。");
            }
        }

        /// <summary>  
        /// 根據傳入的Key獲取配置檔案中的Value值
        /// </summary>
        /// <param name="Key"></param>  
        /// <returns></returns> 
        public static string GetConfigValueByKey(string Key)
        {
            try
            {
                return ConfigurationManager.AppSettings[Key].ToString();
            }
            catch
            {
                throw new Exception("web.config中 Key=\"" + Key + "\"未配置或配置錯誤!");
            }
        }

        /// <summary>
        /// 判斷物件空值或者Null值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Boolean IsNullOrEmpty(Object value)
        {
            if (value == null)
                return true;
            if (String.IsNullOrEmpty(value.ToString()))
                return true;
            return false;
        }
    }
}

DbFactory.cs

/// <summary>
/// 資料庫工廠類
/// </summary>
public class DbFactory
{
    /// <summary>  
    /// 根據配置檔案中所配置的資料庫型別
    /// 來獲取命令引數中的引數符號oracle為":",sqlserver為"@"  
    /// </summary>  
    /// <returns></returns>  
    public static string CreateDbParmCharacter()
    {
        string character = string.Empty;
        switch (AdoHelper.DbType)
        {

            case DbProvider.SQLSERVER:
                character = "@";
                break;
            case DbProvider.ORACLE:
                character = ":";
                break;
            case DbProvider.ACCESS:
                character = "@";
                break;
            default:
                throw new Exception("資料庫型別目前不支援!");
        }
        return character;
    }

    /// <summary>  
    /// 根據配置檔案中所配置的資料庫型別和傳入的  
    /// 資料庫連結字串來建立相應資料庫連線物件 
    /// </summary>  
    /// <param name="connectionString"></param>  
    /// <returns></returns>  
    public static IDbConnection CreateDbConnection(string connectionString)
    {
        IDbConnection conn = null;
        switch (AdoHelper.DbType)
        {
            case DbProvider.SQLSERVER:
                conn = new SqlConnection(connectionString);
                break;
            case DbProvider.ORACLE:
                conn = new OracleConnection(connectionString);
                break;
            case DbProvider.ACCESS:
                conn = new OleDbConnection(connectionString);
                break;
            default:
                throw new Exception("資料庫型別目前不支援!");
        }
        return conn;
    }

    /// 根據配置檔案中所配置的資料庫型別  
    /// 來建立相應資料庫命令物件  
    /// </summary>  
    /// <returns></returns>  
    public static IDbCommand CreateDbCommand()
    {
        IDbCommand cmd = null;
        switch (AdoHelper.DbType)
        {
            case DbProvider.SQLSERVER:
                cmd = new SqlCommand();
                break;
            case DbProvider.ORACLE:
                cmd = new OracleCommand();
                break;
            case DbProvider.ACCESS:
                cmd = new OleDbCommand();
                break;
            default:
                throw new Exception("資料庫型別目前不支援!");
        }
        return cmd;
    }

    /// <summary>  
    /// 根據配置檔案中所配置的資料庫型別  
    /// 來建立相應資料庫介面卡物件  
    /// </summary>  
    /// <returns></returns>  
    public static IDbDataAdapter CreateDataAdapter()
    {
        IDbDataAdapter adapter = null;
        switch (AdoHelper.DbType)
        {
            case DbProvider.SQLSERVER:
                adapter = new SqlDataAdapter();
                break;
            case DbProvider.ORACLE:
                adapter = new OracleDataAdapter();
                break;
            case DbProvider.ACCESS:
                adapter = new OleDbDataAdapter();
                break;
            default:
                throw new Exception("資料庫型別目前不支援!");
        }
        return adapter;
    }

    /// <summary>  
    /// 根據配置檔案中所配置的資料庫型別  
    /// 和傳入的命令物件來建立相應資料庫介面卡物件  
    /// </summary>  
    /// <returns></returns>  
    public static IDbDataAdapter CreateDataAdapter(IDbCommand cmd)
    {
        IDbDataAdapter adapter = null;
        switch (AdoHelper.DbType)
        {
            case DbProvider.SQLSERVER:
                adapter = new SqlDataAdapter((SqlCommand)cmd);
                break;
            case DbProvider.ORACLE:
                adapter = new OracleDataAdapter((OracleCommand)cmd);
                break;
            case DbProvider.ACCESS:
                adapter = new OleDbDataAdapter((OleDbCommand)cmd);
                break;
            default: throw new Exception("資料庫型別目前不支援!");
        }
        return adapter;
    }

    /// <summary>  
    /// 根據配置檔案中所配置的資料庫型別  
    /// 來建立相應資料庫的引數物件  
    /// </summary>  
    /// <returns></returns>  

    public static IDbDataParameter CreateDbParameter()
    {
        IDbDataParameter param = null;
        switch (AdoHelper.DbType)
        {
            case DbProvider.SQLSERVER:
                param = new SqlParameter();
                break;
            case DbProvider.ORACLE:
                param = new OracleParameter();
                break;
            case DbProvider.ACCESS:
                param = new OleDbParameter();
                break;
            default:
                throw new Exception("資料庫型別目前不支援!");
        }
        return param;
    }

    /// <summary>  
    /// 根據配置檔案中所配置的資料庫型別  
    /// 和傳入的引數來建立相應資料庫的引數陣列物件  
    /// </summary>  
    /// <returns></returns>  
    public static IDbDataParameter[] CreateDbParameters(int size)
    {
        int i = 0;
        IDbDataParameter[] param = null;
        switch (AdoHelper.DbType)
        {
            case DbProvider.SQLSERVER:
                param = new SqlParameter[size];
                while (i < size) { param[i] = new SqlParameter(); i++; }
                break;
            case DbProvider.ORACLE:
                param = new OracleParameter[size];
                while (i < size) { param[i] = new OracleParameter(); i++; }
                break;
            case DbProvider.ACCESS:
                param = new OleDbParameter[size];
                while (i < size) { param[i] = new OleDbParameter(); i++; }
                break;
            default:
                throw new Exception("資料庫型別目前不支援!");
        }
        return param;
    }

    /// <summary>  
    /// 根據配置檔案中所配置的資料庫型別  
    /// 來建立相應資料庫的事物物件  
    /// </summary>  
    /// <returns></returns>  
    public static IDbTransaction CreateDbTransaction()
    {
        IDbConnection conn = CreateDbConnection(AdoHelper.ConnectionString);
        if (conn.State == ConnectionState.Closed)
        {
            conn.Open();
        }
        return conn.BeginTransaction();
    }
}  

AdoHelper.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Rizi.Frame.Orm.Common;

namespace Rizi.Frame.Orm.DBUtility
{
    public class AdoHelper 
    {
        //獲取資料庫型別
        private static string strDbType = CommonUtils.GetConfigValueByKey("dbType").ToUpper();

        //將資料庫型別轉換成列舉型別  
        public static DbProvider DbType = DbProviderEnumParse<DbProvider>(strDbType);

         //獲取資料庫連線字串  
        public static string ConnectionString = GetConnectionString("connectionString");
        public static string DbParmChar = DbFactory.CreateDbParmCharacter();
        private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable()); 

        /// <summary>  
        ///通過提供的引數,執行無結果集的資料庫操作命令  
        /// 並返回執行資料庫操作所影響的行數。  
        /// </summary>  
        /// <param name="connectionString">資料庫連線字串</param>  
        /// <param name="commandType">執行命令的型別(儲存過程或T-SQL,等等)</param> 
        /// <param name="commandText">儲存過程名稱或者T-SQL命令列<</param>  
        /// <param name="commandParameters">執行命令所需的引數陣列</param>  
        /// <returns>返回通過執行命令所影響的行數</returns>  
        public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters)  
        {  
            IDbCommand cmd = DbFactory.CreateDbCommand();  

            using (IDbConnection conn = DbFactory.CreateDbConnection(connectionString))  
            {  
                PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);  
                int val = cmd.ExecuteNonQuery();  
                cmd.Parameters.Clear();  
                return val;  
            }  
        }  

        /// <summary>  
        ///通過提供的引數,執行無結果集的資料庫操作命令  
        /// 並返回執行資料庫操作所影響的行數。  
        /// </summary>  
        /// <param name="connectionString">資料庫連線字串</param>  
        /// <param name="commandType">執行命令的型別(儲存過程或T-SQL,等等)</param>  
        /// <param name="commandText">儲存過程名稱或者T-SQL命令列<</param>  
        /// <returns>返回通過執行命令所影響的行數</returns>  
        public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText)  
        {  
            IDbCommand cmd = DbFactory.CreateDbCommand();  

            using (IDbConnection conn = DbFactory.CreateDbConnection(connectionString))  
            {  
                PrepareCommand(cmd, conn, null, cmdType, cmdText, null);  
                int val = cmd.ExecuteNonQuery();  
                cmd.Parameters.Clear();  
                return val;  
            }  
        }  

        /// <summary>  
        ///通過提供的引數,執行無結果集返回的資料庫操作命令  
        ///並返回執行資料庫操作所影響的行數。  
        /// </summary>  
        /// <remarks>  
        /// e.g.:    
        ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));  
        /// </remarks>  
        /// <param name="conn">資料庫連線物件</param>  
        /// <param name="commandType">執行命令的型別(儲存過程或T-SQL,等等)</param>  
        /// <param name="commandText">儲存過程名稱或者T-SQL命令列</param>  
        /// <param name="commandParameters">執行命令所需的引數陣列</param>  
        /// <returns>返回通過執行命令所影響的行數</returns>  
        public static int ExecuteNonQuery(IDbConnection connection, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters)  
        {  
            IDbCommand cmd = DbFactory.CreateDbCommand();  
            PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);  
            int val = cmd.ExecuteNonQuery();  
            cmd.Parameters.Clear();  
            return val;  
        }  
        /// <summary>  
        ///通過提供的引數,執行無結果集返回的資料庫操作命令  
        ///並返回執行資料庫操作所影響的行數。  
        /// </summary>  
        /// <remarks>  
        /// e.g.:    
        ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));  
        /// </remarks>  
        /// <param name="conn">資料庫連線物件</param>  
        /// <param name="commandType">執行命令的型別(儲存過程或T-SQL,等等)</param>  
        /// <param name="commandText">儲存過程名稱或者T-SQL命令列</param>  
        /// <returns>返回通過執行命令所影響的行數</returns>  
        public static int ExecuteNonQuery(IDbConnection connection, CommandType cmdType, string cmdText)  
        {  
            IDbCommand cmd = DbFactory.CreateDbCommand();  
            PrepareCommand(cmd, connection, null, cmdType, cmdText, null);  
            int val = cmd.ExecuteNonQuery();  
            cmd.Parameters.Clear();  
            return val;  
        }  

        /// <summary>  
        ///通過提供的引數,執行無結果集返回的資料庫操作命令  
        ///並返回執行資料庫操作所影響的行數。  
        /// </summary>  
        /// <remarks>  
        /// e.g.:    
        ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));  
        /// </remarks>  
        /// <param name="trans">sql事務物件</param>  
        /// <param name="commandType">執行命令的型別(儲存過程或T-SQL,等等)</param>  
        /// <param name="commandText">儲存過程名稱或者T-SQL命令列<</param>  
        /// <param name="commandParameters">執行命令所需的引數陣列</param>  
        /// <returns>返回通過執行命令所影響的行數</returns>  
        public static int ExecuteNonQuery(IDbTransaction trans, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters)  
        {  
            IDbConnection conn = null;  
            if (trans == null)  
            {  
                conn = DbFactory.CreateDbConnection(ConnectionString);  
            }  
            else   
            {  
                conn = trans.Connection;  
            }  

            IDbCommand cmd = DbFactory.CreateDbCommand();  
            PrepareCommand(cmd, conn, trans, cmdType, cmdText, commandParameters);  
            int val = cmd.ExecuteNonQuery();  
            cmd.Parameters.Clear();  
            return val;  
        }  

        /// <summary>  
        ///通過提供的引數,執行無結果集返回的資料庫操作命令  
        ///並返回執行資料庫操作所影響的行數。  
        /// </summary>  
        /// <remarks>  
        /// e.g.:    
        ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));  
        /// </remarks>  
        /// <param name="trans">sql事務物件</param>  
        /// <param name="commandType">執行命令的型別(儲存過程或T-SQL,等等)</param>  
        /// <param name="commandText">儲存過程名稱或者T-SQL命令列<</param>  
        /// <returns>返回通過執行命令所影響的行數</returns>  
        public static int ExecuteNonQuery(IDbTransaction trans, CommandType cmdType, string cmdText)  
        {  
            IDbCommand cmd = DbFactory.CreateDbCommand();  
            PrepareCommand(cmd, trans.Connection, trans, cmdType, cmdText, null);  
            int val = cmd.ExecuteNonQuery();  
            cmd.Parameters.Clear();  
            return val;  
        }  

        /// <summary>  
        /// 使用提供的引數,執行有結果集返回的資料庫操作命令  
        /// 並返回SqlDataReader物件  
        /// </summary>  
        /// <remarks>  
        /// e.g.:    
        ///  SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));  
        /// </remarks>  
        /// <param name="connectionString">資料庫連線字串</param>  
        /// <param name="commandType">執行命令的型別(儲存過程或T-SQL,等等)</param>  
        /// <param name="commandText">儲存過程名稱或者T-SQL命令列<</param>  
        /// <param name="commandParameters">執行命令所需的引數陣列</param>  
        /// <returns>返回SqlDataReader物件</returns>  
        public static IDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters)  
        {  
            IDbCommand cmd = DbFactory.CreateDbCommand();  
            IDbConnection conn = DbFactory.CreateDbConnection(connectionString);  

            //我們在這裡使用一個 try/catch,因為如果PrepareCommand方法丟擲一個異常,我們想在捕獲程式碼裡面關閉  
            //connection連線物件,因為異常發生datareader將不會存在,所以commandBehaviour.CloseConnection  
            //將不會執行。  
            try  
            {  
                PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);  
                IDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);  
                cmd.Parameters.Clear();  
                return rdr;  
            }  
            catch  
            {  
                conn.Close();  
                throw;  
            }  
        }  
        /// <summary>  
        ///使用提供的引數,執行有結果集返回的資料庫操作命令  
        /// 並返回SqlDataReader物件  
        /// </summary>  
        /// <param name="connectionString">資料庫連線字串</param>  
        /// <param name="commandType">執行命令的型別(儲存過程或T-SQL,等等)</param>  
        /// <param name="commandText">儲存過程名稱或者T-SQL命令列<</param>  
        /// <returns>返回SqlDataReader物件</returns>  
        public static IDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText)  
        {  
            IDbCommand cmd = DbFactory.CreateDbCommand();  
            IDbConnection conn = DbFactory.CreateDbConnection(connectionString);  

            //我們在這裡使用一個 try/catch,因為如果PrepareCommand方法丟擲一個異常,我們想在捕獲程式碼裡面關閉  
            //connection連線物件,因為異常發生datareader將不會存在,所以commandBehaviour.CloseConnection  
            //將不會執行。  
            try  
            {  
                PrepareCommand(cmd, conn, null, cmdType, cmdText, null);  
                IDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);  
                cmd.Parameters.Clear();  
                return rdr;  
            }  
            catch  
            {  
                conn.Close();  
                throw;  
            }  
        }  

        /// <summary>  
        /// 查詢資料填充到資料集DataSet中  
        /// </summary>  
        /// <param name="connectionString">資料庫連線字串</param>  
        /// <param name="cmdType">執行命令的型別(儲存過程或T-SQL,等等)</param>  
        /// <param name="cmdText">命令文字</param>  
        /// <param name="commandParameters">引數陣列</param>  
        /// <returns>資料集DataSet物件</returns>  
        public static DataSet dataSet(string connectionString, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters)  
        {  
            DataSet ds = new DataSet();  
            IDbCommand cmd = DbFactory.CreateDbCommand();  
            IDbConnection conn = DbFactory.CreateDbConnection(connectionString);  
            try  
            {  
                PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);  
                IDbDataAdapter sda = DbFactory.CreateDataAdapter(cmd);  
                sda.Fill(ds);  
                return ds;  
            }  
            catch  
            {  
                conn.Close();  
                throw;  
            }  
            finally  
            {  
                conn.Close();  
                cmd.Dispose();  
            }  
        }  

        /// <summary>  
        /// 查詢資料填充到資料集DataSet中  
        /// </summary>  
        /// <param name="connectionString">資料庫連線字串</param>  
        /// <param name="cmdType">執行命令的型別(儲存過程或T-SQL,等等)</param>  
        /// <param name="cmdText">命令文字</param>  
        /// <returns>資料集DataSet物件</returns>  
        public static DataSet dataSet(string connectionString, CommandType cmdType, string cmdText)  
        {  
            DataSet ds = new DataSet();  
            IDbCommand cmd = DbFactory.CreateDbCommand();  
            IDbConnection conn = DbFactory.CreateDbConnection(connectionString);  
            try  
            {  
                PrepareCommand(cmd, conn, null, cmdType, cmdText, null);  
                IDbDataAdapter sda = DbFactory.CreateDataAdapter(cmd);  
                sda.Fill(ds);  
                return ds;  
            }  
            catch  
            {  
                conn.Close();  
                throw;  
            }  
            finally  
            {  
                conn.Close();  
                cmd.Dispose();  
            }  
        }  

        /// <summary>  
        /// 依靠資料庫連線字串connectionString,  
        /// 使用所提供引數,執行返回首行首列命令  
        /// </summary>  
        /// <remarks>  
        /// e.g.:    
        ///  Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));  
        /// </remarks>  
        /// <param name="connectionString">資料庫連線字串</param>  
        /// <param name="commandType">執行命令的型別(儲存過程或T-SQL,等等)</param>  
        /// <param name="commandText">儲存過程名稱或者T-SQL命令列</param>  
        /// <param name="commandParameters">執行命令所需的引數陣列</param>  
        /// <returns>返回一個物件,使用Convert.To{Type}將該物件轉換成想要的資料型別。</returns>  
        public static object ExecuteScalar(string connectionString, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters)  
        {  
            IDbCommand cmd = DbFactory.CreateDbCommand();  

            using (IDbConnection connection = DbFactory.CreateDbConnection(connectionString))  
            {  
                PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);  
                object val = cmd.ExecuteScalar();  
                cmd.Parameters.Clear();  
                return val;  
            }  
        }  

        /// <summary>  
        /// 依靠資料庫連線字串connectionString,  
        /// 使用所提供引數,執行返回首行首列命令  
        /// </summary>  
        /// <remarks>  
        /// e.g.:    
        ///  Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));  
        /// </remarks>  
        /// <param name="connectionString">資料庫連線字串</param>  
        /// <param name="commandType">執行命令的型別(儲存過程或T-SQL,等等)</param>  
        /// <param name="commandText">儲存過程名稱或者T-SQL命令列</param>  
        /// <returns>返回一個物件,使用Convert.To{Type}將該物件轉換成想要的資料型別。</returns>  
        public static object ExecuteScalar(string connectionString, CommandType cmdType, string cmdText)  
        {  
            IDbCommand cmd = DbFactory.CreateDbCommand();  

            using (IDbConnection connection = DbFactory.CreateDbConnection(connectionString))  
            {  
                PrepareCommand(cmd, connection, null, cmdType, cmdText, null);  
                object val = cmd.ExecuteScalar();  
                cmd.Parameters.Clear();  
                return val;  
            }  
        }  

        /// <summary>  
        ///依靠資料庫連線字串connectionString,  
        /// 使用所提供引數,執行返回首行首列命令  
        /// </summary>  
        /// <remarks>  
        /// e.g.:    
        ///  Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));  
        /// </remarks>  
        /// <param name="conn">資料庫連線物件</param>  
        /// <param name="commandType">執行命令的型別(儲存過程或T-SQL,等等)</param>  
        /// <param name="commandText">儲存過程名稱或者T-SQL命令列</param>