亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

我也來寫:數據庫訪問類DBHelper

2019-11-14 14:01:07
字體:
來源:轉載
供稿:網友

一、前言

  相信許多人都百度過:“.net 數據庫訪問類”。然后就出來一大堆SqlHelper。我也用過這些SqlHelper,也自己寫過,一堆靜態方法,開始使用起來感覺很不錯,它們也確實在很多時候可以很好的工作。ADO.NET已經封裝很好了,我們很容易就可以實現自己的數據庫訪問類。

  很久前,忘記在哪里看到過了,有一個朋友寫了一篇【如何做一個好用的數據庫訪問類】(有興趣的朋友仍然可以搜索到),這篇文章確實寫得很好,作者很詳細的講解了如何設計一個好的數據庫訪問類;所謂“好“是指:輕量、易用、通用、高效。

  其實代碼是很久前就實現了,只是現在才總結記錄,希望可以分享一下學習的過程。ok,在開始前先來看幾個ADO.NET常見的面試題:

1. ADO.NET 5個核心對象是哪5個?

2. 與ADO.NET 相關對象中,哪些可以用于數據綁定?

3. DataSet與DataReader有什么區別?分別適用在什么情況?

二、需求

  這是一個簡單的、基于ADO.NET的數據庫訪問類,它最起碼要具備以下特點:  

1. 支持多種數據庫

  搞.net的視乎有一個固定的思維:數據庫就是用sql server。額,只是很多用sql server,但不是全部,也有很多用 my sql 等的。我們并不能限制一定用什么數據庫。

2. 支持多個數據庫

  有時候我們的應用程序會用到多個數據庫,并且這些數據庫還不是部署在同一臺服務器上的。

3. 簡單

  滿足常見的操作。

4. 可擴展

  可以隨時增加新的方法;對于具體的數據源,也可以有特有的操作。

三、主要說明

3.1 使用DbPRoviderFactory

  既然要支持多種數據庫,那么我們之前常寫的SqlConnection、SqlCommand 就都不能用了,因為它們是針對sql server 數據源的。如果換成 my sql 就是 MySQLConnection, Oracle 就是 OracleConnection 了。

  既然有那么多種Connection,很多朋友可能會想到通過設計模式來處理,例如定義一個父類(或接口),然后各種類型的數據庫繼承它,然后再通過一個工廠,來創建所需要的對象;以后要增加哪種類型的數據庫就再增加一個對應的類就可以了。大概是像下面這樣:

    public abstract class DBHelper    {        public abstract void Open(string key){}        public abstract int ExecuteNonQuery() { }        public abstract object ExecuteScalar() { }        public abstract DataSet GetDataSet() { }    }    public class SqlHelper : DBHelper    {        const char _prefix = '@';        //實現抽象方法...    }    public class MySqlHelper : DBHelper    {        const char _prefix = "@";        //實現抽象方法...    }    public class OracleHelper : DBHelper    {        const char _prefix = ":";        //實現抽象方法...    }    public class DBFactory    {        public static DBHelper GetDBHelper()        {            //根據條件返回DBHelper        }    }

  這樣實現已經比用SqlXXX好很多了,這也是我之前寫過的一種方式。但它仍然不夠靈活,并且實現起來就會發現很多代碼都是類似的,這就與我們上面的簡單的需求相違背了。

  通過上面的分析,我們知道用工廠模式可以解決我們的問題,但這不用我們自己實現,.net 早就提供這樣的工廠:DbProviderFactory。由名稱可以指定DbProviderFactory就是數據源提供程序工廠,負責創建具體的數據源提供程序。它根據 ProviderName就可以創建對應數據源的訪問對象了。這樣我們的實現也由具體變成抽象了,具體的SqlConection變成了抽象的DbConnection。

  什么是 ProviderName? 在配置 web.config 的connectionStrings 時,就會有一個 providerNmae 屬性,例如sql server就是 ”System.Data.SqlClient“,這個名稱空間就是對應的數據源提供程序。

3.2 參數問題

  不同數據庫參數查詢的格式可能不一樣,例如 sql server/my sql 支持“@變量” 形式,而 oracle 支持“:變量”的形式。像上面的父類的寫法,子類就必須定義自己的參數前綴。但這些用了DbProviderFactory后也不是問題了。

3.3 using 問題

  我們都知道using是c#的語法糖,其實編譯后就是 try-finaly;uisng寫起來比較優雅,而且在有異常的時候會自動調用對象的Disponse方法,避免有些人忘記調用。所以嵌套的 using,編譯后就是嵌套的try-finaly,但其實只要我們注意在拋異常的時候釋放資源,一個try-finaly即可。

3.4 DbDataReader 問題

  實際項目中,我們更多的是使用DbDataReader而非DataSet/DataTable,而 DbDataReader需要自己逐行讀取,這在每個調用的地方都這樣寫是很麻煩的,怎么解決?委托,又是它!

  說到委托還有一個小小的建議,有些人喜歡自己去定義委托,但其實.net已經內置了3種委托:Func、Action、Predicate,并且提供了多個重載版本,應該優先考慮使用這些委托,在不滿足的情況下,再去自定義。

3.5 在分層架構里的角色

  為 DAL 層提供數據訪問服務,由 DAL 直接調用;不涉及sql語句拼接、日志記錄等。

四、例子

  假設要調用一個 P_GetFriends存儲過程,接收一個id參數,返回一個好友列表。如下:

        public List<Friend> GetFriends(int id)        {            try            {                                DBHelper helper = new DBHelper("dbConnectionKey");                DbParameter[] parameters = new DbParameter[]                {                    helper.CreateDbParameter("id",id)                };                return helper.ExecuteReader(CommandType.StoredProcedure, "P_GetFriends", parameters,                reader =>                {                    return new Friend()                    {                        ID = reader.GetInt32(reader.GetOrdinal("ID")),                        Name = reader.GetString(reader.GetOrdinal("Name"))                    };                });            }            catch            {                throw;            }        }  

附源代碼

    public class DBHelper    {        #region 屬性        /// <summary>        /// 鏈接字符串        /// </summary>        private string conStr;        /// <summary>        /// DB工廠        /// </summary>        private DbProviderFactory provider;        #endregion        #region 構造函數        /// <summary>        /// 構造函數        /// </summary>        /// <param name="key">鏈接字符串鍵</param>        public DBHelper(string key)        {            if (string.IsNullOrEmpty(key))            {                throw new ArgumentNullException("key");            }            ConnectionStringSettings CSS = WebConfigurationManager.ConnectionStrings[key];            if (css == null)            {                throw new InvalidOperationException("未找到指定的鏈接字符串!");            }            this.conStr = css.ConnectionString;            this.provider = DbProviderFactories.GetFactory(css.ProviderName);        }        /// <summary>        /// 構造函數        /// </summary>        /// <param name="conStr">鏈接字符串</param>        /// <param name="providerStr">數據源提供程序</param>        public DBHelper(string conStr, string providerStr)        {            if (string.IsNullOrEmpty(conStr))            {                throw new ArgumentNullException("conStr");            }            if (string.IsNullOrEmpty(providerStr))            {                throw new ArgumentNullException("providerStr");            }            this.provider = DbProviderFactories.GetFactory(providerStr);            this.conStr = conStr;        }        #endregion        #region 外部方法        /// <summary>        /// 執行命令,返回受影響行數        /// </summary>        /// <param name="commandType">命令類型</param>        /// <param name="sql">sql語句或存儲過程名稱</param>        /// <param name="parameters">參數數組</param>        /// <returns>受影響行數,失敗返回-1</returns>        public virtual int ExecuteNonQuery(CommandType commandType, string sqlOrProcName, IEnumerable<DbParameter> parameters)        {            DbConnection con = CreateConnection();            DbCommand cmd = CreateCommand(con, commandType, sqlOrProcName, parameters);            try            {                con.Open();                return cmd.ExecuteNonQuery();            }            finally            {                cmd.Dispose();                con.Dispose();            }        }        /// <summary>        /// 執行命令,返回第一行第一列對象        /// </summary>        /// <param name="commandType">命令類型</param>        /// <param name="sql">sql語句或存儲過程名稱</param>        /// <param name="parameters">參數數組</param>        /// <returns>執行結果</returns>        public virtual object ExecuteScalar(CommandType commandType, string sqlOrProcName, IEnumerable<DbParameter> parameters)        {            DbConnection con = CreateConnection();            DbCommand cmd = CreateCommand(con, commandType, sqlOrProcName, parameters);            try            {                con.Open();                return cmd.ExecuteScalar();            }            finally            {                cmd.Dispose();                con.Dispose();            }        }        /// <summary>        /// 執行命令返回DataSet        /// </summary>        /// <param name="commandType">命令類型</param>        /// <param name="sql">sql語句或存儲過程名稱</param>        /// <param name="parameters">參數數組</param>        /// <returns>DataSet</returns>        public virtual DataSet GetDataSet(CommandType commandType, string sqlOrProcName, IEnumerable<DbParameter> parameters)        {            DbConnection con = CreateConnection();            DbCommand cmd = CreateCommand(con, commandType, sqlOrProcName, parameters);            DataSet set = new DataSet();            DbDataAdapter adapter = this.provider.CreateDataAdapter();            try            {                con.Open();                adapter.SelectCommand = cmd;                adapter.Fill(set);                return set;            }            finally            {                adapter.Dispose();                cmd.Dispose();                con.Dispose();            }        }        /// <summary>        /// 執行命令返回DbDataReader        /// </summary>        /// <param name="commandType">命令類型</param>        /// <param name="sql">sql語句或存儲過程名稱</param>        /// <param name="parameters">參數數組</param>        /// <param name="action">委托</param>        /// <returns>對象列表</returns>        public virtual List<T> ExecuteReader<T>(CommandType commandType, string sqlOrProcName, IEnumerable<DbParameter> parameters,            Func<DbDataReader, T> action)        {            DbConnection con = CreateConnection();            DbCommand cmd = CreateCommand(con, commandType, sqlOrProcName, parameters);            DbDataReader reader = null;            List<T> result = new List<T>();            try            {                con.Open();                reader = cmd.ExecuteReader();                                while (reader.Read())                {                    var item = action(reader);                    result.Add(item);                }                return result;                           }            finally            {                if (reader != null)                {                    reader.Dispose();                }                cmd.Dispose();                con.Dispose();            }        }        /// <summary>        /// 批量執行sql語句        /// </summary>        /// <param name="sqlList">sql語句集合</param>        /// <param name="paramList">參數數組集合</param>        /// <returns>執行成功或失敗</returns>        public virtual bool ExecuteSqlBatchByTrans(IEnumerable<string> sqlList, IEnumerable<List<DbParameter>> paramList)        {            DbConnection con = CreateConnection();            DbCommand cmd = CreateCommand(con, CommandType.Text);            DbTransaction trans = null;            try            {                con.Open();                trans = con.BeginTransaction();                cmd.Transaction = trans;                int length = sqlList.Count();                IEnumerable<DbParameter> parameters = null;                for (int i = 0; i < length; i++)                {                    cmd.CommandText = sqlList.ElementAt<string>(i);                    cmd.Parameters.Clear();                    parameters = paramList.ElementAt<List<DbParameter>>(i);                    foreach (DbParameter pm in parameters)                    {                        cmd.Parameters.Add(pm);                    }                    cmd.ExecuteNonQuery();                }                trans.Commit();                return true;            }            catch            {                if (trans != null)                {                    trans.Rollback();                }                throw;            }            finally            {                if (trans != null)                {                    trans.Dispose();                }                cmd.Dispose();                con.Dispose();            }        }        #endregion        #region CreateDbParameter        public DbParameter CreateDbParameter(string name, object value)        {            DbParameter parameter = this.provider.CreateParameter();            parameter.ParameterName = name;            parameter.Value = value;            return parameter;        }        public DbParameter CreateDbParameter(string name, object value, ParameterDirection direction)        {            DbParameter parameter = this.provider.CreateParameter();            parameter.ParameterName = name;            parameter.Value = value;            parameter.Direction = direction;            return parameter;        }        public DbParameter CreateDbParameter(string name, object value, int size)        {            DbParameter parameter = this.provider.CreateParameter();            parameter.ParameterName = name;            parameter.Value = value;            parameter.Size = size;            return parameter;        }        public DbParameter CreateDbParameter(string name, object value, int size, DbType type)        {            DbParameter parameter = this.provider.CreateParameter();            parameter.ParameterName = name;            parameter.Value = value;            parameter.Size = size;            parameter.DbType = type;            return parameter;        }        public DbParameter CreateDbParameter(string name, object value, int size, DbType type, ParameterDirection direction)        {            DbParameter parameter = this.provider.CreateParameter();            parameter.ParameterName = name;            parameter.Value = value;            parameter.Size = size;            parameter.DbType = type;            parameter.Direction = direction;            return parameter;        }        #endregion        #region 私有方法        /// <summary>        /// 獲取鏈接實例        /// </summary>        /// <returns>鏈接實例</returns>        private DbConnection CreateConnection()        {            DbConnection con = this.provider.CreateConnection();            con.ConnectionString = this.conStr;            return con;        }        /// <summary>        /// 獲取命令實例        /// </summary>        /// <param name="con">鏈接實例</param>        /// <param name="commandType">命令類型</param>        /// <param name="sqlOrProcName">sql語句或存儲過程名稱</param>        /// <returns>命令實例</returns>        private DbCommand CreateCommand(DbConnection con, CommandType commandType, string sqlOrProcName, IEnumerable<DbParameter> parameters)        {            DbCommand cmd = InitCommand(con, commandType, parameters);            cmd.CommandText = sqlOrProcName;            return cmd;        }        /// <summary>        /// 獲取命令實例        /// </summary>        /// <param name="con">鏈接實例</param>        /// <param name="commandType">命令類型</param>        /// <returns>命令實例</returns>        private DbCommand CreateCommand(DbConnection con, CommandType commandType)        {            return InitCommand(con, commandType, null);        }        /// <summary>        /// 初始化命令        /// </summary>        /// <param name="commandType">命令類型</param>        /// <param name="parameters">參數集合</param>        /// <returns></returns>        private DbCommand InitCommand(DbConnection con, CommandType commandType, IEnumerable<DbParameter> parameters)        {            DbCommand cmd = con.CreateCommand();            cmd.CommandType = commandType;            if (parameters != null)            {                foreach (DbParameter pm in parameters)                {                    cmd.Parameters.Add(pm);                }            }            return cmd;        }        #endregion    }

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩美女写真福利在线观看| 亚洲电影免费观看| 日韩亚洲欧美中文在线| 日韩av在线最新| 欧美大片大片在线播放| 欧美天天综合色影久久精品| 在线视频免费一区二区| 久久精品国产久精国产一老狼| 国产精品主播视频| 亚洲电影免费观看高清完整版| 国产精品久久久久福利| 国产精品久久色| 亚洲国产精久久久久久久| 久久久噜噜噜久噜久久| 欧美亚洲成人xxx| 日韩成人中文电影| 久久久国产一区二区三区| 疯狂蹂躏欧美一区二区精品| 国产精品久久二区| 亚洲激情视频网| 精品久久久久久久久中文字幕| 亚洲一区二区三区乱码aⅴ| 亚洲日本中文字幕免费在线不卡| 欧美成人性色生活仑片| 国产91精品久久久久| 午夜精品一区二区三区在线| 欧美中在线观看| 日韩高清免费在线| 日韩欧美国产一区二区| 国产精品18久久久久久麻辣| 日本精品在线视频| 国模视频一区二区三区| 日韩精品免费视频| 热99在线视频| 欧美精品18videosex性欧美| 日产日韩在线亚洲欧美| 一区二区三区天堂av| xxxxx91麻豆| 精品人伦一区二区三区蜜桃免费| 91精品视频免费| 日韩视频中文字幕| 欧美日韩一区二区三区在线免费观看| 日韩欧美在线免费| 精品欧美国产一区二区三区| 成人精品一区二区三区电影黑人| 亚洲a中文字幕| 91av在线网站| 亚洲精品日韩在线| 欧美日韩国产一区在线| 中文字幕精品—区二区| 欧美成人精品在线播放| 亚洲国产精品免费| 国产精品美女主播| 亚洲精品视频在线观看视频| 91av在线精品| 一本一本久久a久久精品牛牛影视| 日韩av免费在线观看| 91精品久久久久久久久| 国产女人精品视频| 久久精品国产久精国产思思| 亚洲美女av在线播放| 91精品国产综合久久男男| 国产欧美欧洲在线观看| 亚洲综合国产精品| 欧美日韩精品二区| 日韩中文有码在线视频| 色黄久久久久久| 国产精品aaaa| 亚洲精品www久久久| 欧美激情一区二区三区成人| 欧美日韩国产页| 热久久99这里有精品| 中文字幕一精品亚洲无线一区| 国产日韩欧美自拍| 久热精品视频在线| 欧美日韩福利电影| 亚洲999一在线观看www| 国产女精品视频网站免费| 88xx成人精品| 欧美在线观看网站| 亚洲欧美日韩中文在线| 91系列在线播放| 欧美孕妇与黑人孕交| 亚洲国产精品久久久久秋霞不卡| 亚洲第一区中文字幕| 亚洲码在线观看| 久久久久国产精品免费网站| 亚洲 日韩 国产第一| 疯狂做受xxxx高潮欧美日本| 成人精品视频久久久久| 日韩精品日韩在线观看| 欧美激情xxxx性bbbb| 欧美成人精品三级在线观看| 欧美午夜女人视频在线| 中文字幕久久久av一区| 国产日韩欧美在线| 久久婷婷国产麻豆91天堂| 日韩av在线网| 日韩精品免费综合视频在线播放| 欧美亚洲另类激情另类| xxxx性欧美| 亚洲一区二区三区xxx视频| 亚洲a一级视频| www.亚洲免费视频| 精品五月天久久| 久久人人爽亚洲精品天堂| 亚洲国产精品小视频| 国产成人精品电影久久久| 成人情趣片在线观看免费| 日韩一区二区三区国产| 欧美中文字幕在线| 精品亚洲国产视频| 亚洲精品自拍偷拍| 热草久综合在线| 日韩福利伦理影院免费| 一区国产精品视频| 亚洲男人天堂九九视频| 伊人久久男人天堂| 欧美日韩精品在线| 欧美国产一区二区三区| 国产97人人超碰caoprom| 国产精品免费久久久久影院| 国产欧美精品va在线观看| 不卡伊人av在线播放| 欧美中在线观看| 日本亚洲欧美成人| 成人综合网网址| 欧美一区二区三区免费观看| 黄网动漫久久久| 精品国产一区二区在线| x99av成人免费| 久久精品中文字幕免费mv| 亚洲一区二区三区乱码aⅴ| 日韩女优人人人人射在线视频| 亚洲精品理论电影| 国产九九精品视频| 久久久久久久久亚洲| 国产日产亚洲精品| 福利微拍一区二区| 久久在线视频在线| 88国产精品欧美一区二区三区| 91精品免费久久久久久久久| 成人亚洲综合色就1024| 久久久99免费视频| 成人午夜激情网| 国产精品网站大全| 在线观看成人黄色| 成人免费看吃奶视频网站| 久久成人在线视频| 欧美黑人巨大精品一区二区| 亚洲美女av在线| 91免费观看网站| 国产日本欧美一区| 亚洲欧美日韩精品| 国产亚洲人成网站在线观看| 欧美日韩亚洲一区二区三区| 欧美夜福利tv在线| 欧美专区国产专区| 亚洲女同精品视频| 热久久这里只有| 国产精品成久久久久三级| 欧美影院在线播放| 91欧美精品午夜性色福利在线| 欧美激情综合色综合啪啪五月|