代碼中添加事務控制 VS(資料庫預存程序+事務) 保證資料的完整性與一致性

來源:互聯網
上載者:User

        做人事檔案的系統考慮到資料的安全性與一致性,畢竟是要對外上線、真正投入使用的項目,資料庫的可靠性與安全性上我們開發人員要考慮的就很多了,記得做機房收費系統時註冊新卡是自己為了簡單,寫成了一個預存程序(預存程序加事務),完成了一個功能的實現就萬事大吉了,這次想換一種新的方法:經過和師哥的交流學習,在代碼中使用事務同樣也是可以解決問題的,可以保證資料的正確性,就像銀行取款一樣,如果在取款的過程中取款機出現故障,我們個人的賬戶上的金額不會受任何影響等。

 

         代碼中使用事務前提:務必保證一個功能(或用例)在同一個開啟的資料連線上,放到同一個事務裡面操作。



        首先是在D層添加一個類為了儲存當前操作的這一個串連放到一個事務中執行,並事務執行開啟同一個串連、事務完成關閉同一個串連的一個共有類

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data;using System.Data.SqlClient;using Maticsoft.DBUtility;namespace PersonalFiles.DAL{    public class DBTransaction    {        private DbHelperSQL SqlHelper = null;        public DBTransaction()        {            SqlHelper = new DbHelperSQL();        }        /// <summary>        /// 擷取資料庫連接        /// </summary>        /// <returns></returns>        public SqlConnection GetConnection()        {            return SqlHelper.GetCon();        }        /// <summary>        /// 擷取事務        /// </summary>        /// <returns></returns>        public SqlTransaction GetTransaction(SqlConnection conn)        {            return conn.BeginTransaction();        }        /// <summary>        /// 提交事務        /// </summary>        public void Commit(SqlTransaction sqlTransaction)        {            sqlTransaction.Commit();        }        /// <summary>        /// 復原事務        /// </summary>        public void Rollback(SqlTransaction sqlTransaction)        {            sqlTransaction.Rollback();        }        /// <summary>        /// 關閉串連        /// </summary>        public void Close(SqlConnection conn)        {            if (conn.State == ConnectionState.Open)            {                conn.Close();            }        }    }}



        介面層的後台代碼和以前一樣直接調去就行了,現在來看主要是在B層中的代碼發生了很大的變化,需要向下層傳遞事務與擷取的串連


/// <summary>        /// 增加一條資料        /// </summary>        public void Add(PersonalFiles.Model.BasicInformation modelBasic, PersonalFiles.Model.T_HumanAgency model)        {            int flag = 0;            DBTransaction DbTran = new DBTransaction();            //獲得串連            SqlConnection conn = DbTran.GetConnection();                        //開啟事務            SqlTransaction trans = DbTran.GetTransaction(conn);            try            {                //把獲得的同一個串連與事務一共傳下去                //dalBasic.Add(modelBasic,conn,trans);                               //把獲得的同一個串連與事務一共傳下去                               dalAgency.Add(model,conn,trans);                        //事務提交                DbTran.Commit(trans);                //return true;            }            catch (Exception ex)            {                //復原事務                DbTran.Rollback(trans);            }            finally            {                DbTran.Close(conn);            }        }


注意的是向D層傳是我們需要傳的是B層擷取的同一個串連於開啟的是一個事務:


/// <summary>        /// 增加一條資料        /// </summary>        public void Add(PersonalFiles.Model.T_HumanAgency model,SqlConnection conn,SqlTransaction trans)        {            StringBuilder strSql = new StringBuilder();            strSql.Append("insert into T_HumanAgency(");            strSql.Append("myidentity,relation,receivemode,workingtime,intotime,oldworkplace,nowworkplace,inervice,registered,registeredcardid,registeredid,householder,isrecord,fileintotime,fileouttime,filetowhere,relationouttime,Paymentstandard,paymentsmonth,payments,stoptime,state,pri,admin,ID)");            strSql.Append(" values (");            strSql.Append("@myidentity,@relation,@receivemode,@workingtime,@intotime,@oldworkplace,@nowworkplace,@inervice,@registered,@registeredcardid,@registeredid,@householder,@isrecord,@fileintotime,@fileouttime,@filetowhere,@relationouttime,@Paymentstandard,@paymentsmonth,@payments,@stoptime,@state,@pri,@admin,@ID)");            SqlParameter[] parameters = {new SqlParameter("@myidentity", SqlDbType.VarChar,50),new SqlParameter("@relation", SqlDbType.VarChar,50),new SqlParameter("@receivemode", SqlDbType.VarChar,50),new SqlParameter("@workingtime", SqlDbType.VarChar,50),new SqlParameter("@intotime", SqlDbType.VarChar,50),new SqlParameter("@oldworkplace", SqlDbType.VarChar,50),new SqlParameter("@nowworkplace", SqlDbType.VarChar,50),new SqlParameter("@inervice", SqlDbType.VarChar,50),new SqlParameter("@registered", SqlDbType.VarChar,50),new SqlParameter("@registeredcardid", SqlDbType.VarChar,50),new SqlParameter("@registeredid", SqlDbType.VarChar,50),new SqlParameter("@householder", SqlDbType.VarChar,50),new SqlParameter("@isrecord", SqlDbType.VarChar,50),new SqlParameter("@fileintotime", SqlDbType.VarChar,50),new SqlParameter("@fileouttime", SqlDbType.VarChar,50),new SqlParameter("@filetowhere", SqlDbType.VarChar,50),new SqlParameter("@relationouttime", SqlDbType.VarChar,50),new SqlParameter("@Paymentstandard", SqlDbType.VarChar,50),new SqlParameter("@paymentsmonth", SqlDbType.VarChar,50),new SqlParameter("@payments", SqlDbType.VarChar,50),new SqlParameter("@stoptime", SqlDbType.VarChar,50),new SqlParameter("@state", SqlDbType.VarChar,50),new SqlParameter("@admin", SqlDbType.VarChar,50),                    new SqlParameter("@pri", SqlDbType.VarChar,50),new SqlParameter("@ID", SqlDbType.VarChar,50)};            parameters[0].Value = model.myidentity;            parameters[1].Value = model.relation;            parameters[2].Value = model.receivemode;            parameters[3].Value = model.workingtime;            parameters[4].Value = model.intotime;            parameters[5].Value = model.oldworkplace;            parameters[6].Value = model.nowworkplace;            parameters[7].Value = model.inervice;            parameters[8].Value = model.registered;            parameters[9].Value = model.registeredcardid;            parameters[10].Value = model.registeredid;            parameters[11].Value = model.householder;            parameters[12].Value = model.isrecord;            parameters[13].Value = model.fileintotime;            parameters[14].Value = model.fileouttime;            parameters[15].Value = model.filetowhere;            parameters[16].Value = model.relationouttime;            parameters[17].Value = model.Paymentstandard;            parameters[18].Value = model.paymentsmonth;            parameters[19].Value = model.payments;            parameters[20].Value = model.stoptime;            parameters[21].Value = model.state;            parameters[22].Value = model.pri;            parameters[23].Value = model.admin;            parameters[24].Value = model.ID;                      //DbHelperSQL.ExecuteSql(strSql.ToString(), parameters);            DbHelperSQL.ExecuteSql(strSql.ToString(),conn,trans, parameters);        }


在代碼中添加事務與預存程序中添加事務的異同

     相同點

1:都能夠保證資料的一致性。


     不同點:

1:代碼中添加事務的好處是:增加了代碼的可讀性、與可維護性,方便後期人員維護系統看代碼能夠一目瞭然的看懂代碼,而在資料庫中添加預存程序的可讀性不是很好。


2:為什麼不建議使用資料庫內建的預存程序+事務呢?主要是一個項目過多的依賴資料庫,這樣對後期的資料庫遷移都會帶來一定的影響與不便(sql向oracle遷移),好多轉換不是很容易相容性和不是很好(以後再深入學習)。


3:合作開發時如果是代碼中添加事務遵循了代碼上傳的原則,這樣方便大家的交流。



為什麼使用事務可以保證同一個串連向資料庫多個表寫資訊的正確性與一致性的原理:


 事務的原子性

事務的原子性指的是,事務中包含的程式作為資料庫的邏輯工作單位,它所做的對資料改操作要全部執行,要麼全部不執行。這種特性稱為原子性。  事務的原子性要求,如果把一個事務看作是一個程式,它要麼完整的被執行,要麼完全執行。就是說事務的操縱序列或者完全應用到資料庫或者完全不影響資料庫。這種特性稱為原則性  假如使用者在一個事務內完成了對資料庫的更新,這時所有的更新對外部世界必須是可見的,或者完全沒有更新。前者稱事務已提交,後者稱事務撤銷。DBMS必須確保由成功提交的事物完成的所有操作在資料庫內有完全的反映,而失敗的交易對資料庫完全沒有影響


事務的隔離性

 事務開始執行了但是沒有提交事務,資料並沒有真正的寫到資料庫裡面,當我去斷點測試的時候當第一個程式向資料庫發出寫完時,我去尋找資料庫不能開啟資料庫,不能尋找,提示連線逾時,由於事務的隔離性,資料並沒有真正的寫到資料庫裡面,等事務提交才可以查到資料庫,可見同一個串連下執行的程式在同一個事務執行的開始於結束後才真正寫到資料庫裡面,如果過程當中儲存交易回復,資料不會寫到資料庫裡面。保證資料的一致性與正確性。

資料的準確性與一致性是我們要時刻考慮的,一個好的系統必須有較好的準確性才能保證使用者的使用。






聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.