国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

c# 輕量級 ORM 框架 之 DBHelper 實現(xiàn) (三)

2019-11-17 03:04:47
字體:
供稿:網(wǎng)友

c# 輕量級 ORM 框架 之 DBHelper 實現(xiàn) (三)

  周末了比較清閑,把自己的orm框架整理了下,開源了.

  已經(jīng)做出來的東西通常感覺有些簡單,一些新手或許聽到"框架"一類的詞覺得有些"高深",簡單來說orm就是把ado的封裝.

在介紹這個框架的第一篇博文,已經(jīng)把DalBase介紹了一下設計思路,本篇的DBHelper對象也是給dalBase來用的,可以說框架的所有定義對象都是為了它.

這里起名叫DBHelper,因為我也是從寫SQLHelper開始的,DBHelper只不過是所有類型對ado操作的各種方法的封裝,所以本篇博文希望給c#新手,或是對ado.net認識比較模糊的有一些幫助.

首先DBHelper定義是個抽象的,因為我不知道DalBase 到底要訪問哪種數(shù)據(jù)庫,但我知道不管哪中數(shù)據(jù)庫都會有鏈接字符串,那我就要求,必須要有連接字符串.

public DbHelperBase(string connStr)        {            _ConnStr = connStr;        }
View Code

DbHelper是個抽象的,那它的成員必然就不能有具體對象.

那就把ado.net常用的對象定義出來.(如果你是初學者,我的建議是 用到哪個對象再去定義,否則到后期自己都不知道定義它干啥呢)

        PRotected abstract DbConnection DBConnectionObj { get; }        protected abstract DbCommand DbCommandObj { get; }        protected abstract DbDataAdapter DbDataAdapterObj { get; }        protected DbTransaction DbTransObj;        public DbConnection CurrentConnection        {            get            {                return DBConnectionObj;            }        }  

說明一下,為什么事務對象不是抽象的,因為事務對象始終是有DbConnection來創(chuàng)建的,我不用知道它具體是什么類型.

DbConnection 對象public也是為了擴展其它功能而存在的.

定義了是否事務的變量,所有ado操作都會判斷當前是否處于事務的標記.

bool _IsTrans = false;

初學.net的朋友,應該都會有一個SQLHelper的類,我也曾經(jīng)看過都大同小異,而且普遍都沒有事務的實現(xiàn),如果你中槍了,那么恭喜你,你即將會改變你sqlHelper的實現(xiàn).

如下代碼:

     /// <summary>        /// 執(zhí)行一條指定命令類型(SQL語句或存儲過程等)的SQL語句,返回所影響行數(shù)        /// </summary>        public int ExecNonQuery(string sqlText, CommandType cmdType, params DbParameter[] param)        {            using (SqlConnection conn = new SqlConnection(_ConnStr))            {                using (SqlCommand cmd = new SqlCommand(sqlText, conn))                {                    cmd.CommandType = cmdType;                    if (param != null)                        cmd.Parameters.AddRange(param);                    conn.Open();                    return cmd.ExecuteNonQuery();                }            }        }

以上代碼看起來是沒什么問題,但如果要啟用事務的話想想是否可以實現(xiàn)呢?

如果說改造一下加上事務的代碼就行的話

如下:

 SqlTransaction tran = conn.BeginTransaction(); cmd.Transaction = tran;   

這樣顯然是錯的,因為我們往往多條執(zhí)行語句通常是分多次調(diào)用ExecNonQuery() 方法的.

這樣的一個ado方法的封裝顯然是不合理的.

如果多個增刪改查(注意:查詢也可能在是事務里)的方法,在一個事務里,那么必須是一個數(shù)據(jù)庫連接(Connection)

這就是為什么把那三個對象定義到外面的原因之一了,最重要的原因是我需要子類去重寫它.

下面看看我的實現(xiàn):

        /// <summary>        /// 打開連接,如果已經(jīng)打開則什么都不執(zhí)行了        /// </summary>        void OpenConnection()        {            if (DBConnectionObj.State != ConnectionState.Open)            {                DBConnectionObj.ConnectionString = _ConnStr;                DBConnectionObj.Open();            }        }
        /// <summary>        /// 給當前DbCommand對象賦值,并且OpenConnection();        /// </summary>        void SetCommandAndOpenConnect(string sqlText, CommandType cmdType, params DbParameter[] param)        {            //按說賦值Connection,CommandType,是不用多次賦值的            DbCommandObj.CommandType = cmdType;            DbCommandObj.Connection = DBConnectionObj;            DbCommandObj.Parameters.Clear();            if (param != null)            {                DbCommandObj.Parameters.AddRange(param);            }            DbCommandObj.CommandText = sqlText;            OpenConnection();        }
        /// <summary>        /// 執(zhí)行一條指定命令類型(SQL語句或存儲過程等)的SQL語句,返回所影響行數(shù)        /// </summary>        public int ExecNonQuery(string sqlText, CommandType cmdType, params DbParameter[] param)        {            try            {                SetCommandAndOpenConnect(sqlText, cmdType, param);                return DbCommandObj.ExecuteNonQuery();            }            catch (Exception ex)            {                throw ex;            }            finally            {                CloseConnect();            }        }

看到這三個方法或許對于初學者會感到迷茫了,沒有看到任何有關事務的代碼呢,兜個圈子,現(xiàn)在想象一下如果加事務的話,需要做什么?

我們先從理論上認識一下,事務處理的流程

1.指定事務是哪個Connection

2.Command的事務對象指定到該事務.

3.Open()

4.提交或回滾(我是能寫漢字的地方絕不寫拼音)

5.關閉連接.

繼續(xù)說這幾個方法,為什么定義SetCommandAndOpenConnect 和OpenConnection這兩個方法,本著盡量減少重復代碼的原則.僅此而已.

既然Connection和Command都已經(jīng)定義到方法外了,那就是說我只要再執(zhí)行Command.ExecuteNonQuery()方法前,給他們賦值就行了.

也就是開始事務只需要給這個兩個對象賦值即可

事務的相關代碼如下:

        /// <summary>        /// 開始執(zhí)行事務        /// </summary>        public void TransStart()        {            OpenConnection();            DbTransObj = DBConnectionObj.BeginTransaction();            DbCommandObj.Transaction = DbTransObj;            _IsTrans = true;        }        /// <summary>        /// 事務提交        /// </summary>        public void TransCommit()        {            _IsTrans = false;            DbTransObj.Commit();            CloseConnect();        }        /// <summary>        /// 事務回滾        /// </summary>        public void TransRollback()        {            _IsTrans = false;            DbTransObj.Rollback();            CloseConnect();        }

這就是事務的方法了.

最后一個CloseConnect()方法,差點把它遺忘了

        /// <summary>        /// 關閉連接,如果沒有開始事務或連接打開時才關閉        /// </summary>        void CloseConnect()        {            if (!_IsTrans)            {                if (DBConnectionObj.State == ConnectionState.Open)                {                    DBConnectionObj.Close();                    DBConnectionObj.Dispose();                }            }        }

當開始事務時,連接是不能關的.只有提交了或回滾了才會把當前連接斷掉.

到這里其實DbHelper的設計基本完成,再貼一下關于查詢的幾個方法,和執(zhí)行類似就不解釋了.

     /// <summary>        /// 獲得首行首列        /// </summary>        public object GetScalar(string sqlText, CommandType cmdType, params DbParameter[] param)        {            try            {                SetCommandAndOpenConnect(sqlText, cmdType, param);                return DbCommandObj.ExecuteScalar();            }            catch (Exception ex)            {                throw ex;            }            finally            {                CloseConnect();            }        }     /// <summary>        /// 執(zhí)行一條SQL語句返回DataSet對象        /// </summary>        public DataSet GetDataSet(string sqlText, CommandType cmdType, params DbParameter[] param)        {            try            {                SetCommandAndOpenConnect(sqlText, cmdType, param);                DbDataAdapterObj.SelectCommand = DbCommandObj;                DataSet ds = new DataSet();                DbDataAdapterObj.Fill(ds);                return ds;            }            catch (Exception ex)            {                throw ex;            }            finally            {                CloseConnect();            }        }     /// <summary>        /// 獲得DataReader對象        /// </summary>        public DbDataReader GetDataReader(string sqlText, CommandType cmdType, params DbParameter[] param)        {            try            {                SetCommandAndOpenConnect(sqlText, cmdType, param);                CommandBehavior cmdBehavior = CommandBehavior.CloseConnection;                if (_IsTrans)                {                    cmdBehavior = CommandBehavior.Default;                }                DbDataReader dbReader = DbCommandObj.ExecuteReader(cmdBehavior);                return dbReader;            }            catch (Exception ex)            {                throw ex;            }            finally            {                //DataReader用dbReader對象來關閉                //CloseConnect();            }        }

這里需要注意的是關于返回DataReader對象時不能關閉Connect,和cmdBehavior 的賦值.

好了,到這DBHelper的設計和核心代碼已經(jīng)全部實現(xiàn)了.

試想一下我現(xiàn)在要完成SQLServerHelper的實現(xiàn)需要做的是什么?

當然只要實現(xiàn)父類的那幾個抽象屬性就行了.

代碼如下:

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 满城县| 丘北县| 双牌县| 拜泉县| 革吉县| 周至县| 松潘县| 通海县| 拉萨市| 商都县| 合江县| 庆云县| 城口县| 太和县| 开原市| 乌兰察布市| 黎川县| 荥阳市| 芮城县| 芒康县| 中西区| 徐闻县| 莒南县| 浪卡子县| 石渠县| 恭城| 措勤县| 甘泉县| 阿图什市| 泽普县| 咸阳市| 淮阳县| 洪雅县| 齐齐哈尔市| 美姑县| 新营市| 达拉特旗| 仁怀市| 信丰县| 中山市| 浏阳市|