中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

EF架構~通過EF6的(de)DbCommand攔截器來實現數據庫讀寫(xie)分離(li)~續~添(tian)加(jia)事務機制

回到目錄

上一講中簡單介紹了一個EF環境下通過DbCommand攔截器來實現SQLSERVER的讀寫分離,只是一個最簡單的實現,而如果出現事務情況,還是會有一些問題的,因為在攔截器中我們手動開啟了Connection鏈接,而在一個WEB請求時,如果你的一個變量即用到了read庫又用到了write庫,就會導致到sqlserver端的spid(system process id,系統進程ID,sqlserver里可能是某個數據庫進程序的ID)發生變化 ,而對于這種變化,原本是本地的事務就會自動提升為分布式事務,對MSDTC不了解的同學,可能看我的相關文章,所以,我們使用攔截實現讀寫分離后,在程序里,你的讀和寫的倉儲對象要分別定義,不能共享,而且,你在事務里所以寫的倉儲對象都要使用同一個數據上下文!

當你按(an)著我說的做(zuo)后,本地事務(wu)就不會提升為msdtc了,如(ru)圖:

今(jin)天我在(zai)DbCommand攔截器(qi)進行了優化,下面共享一下代(dai)碼,如是(shi)測試不是(shi)真實一項(xiang)目代(dai)碼

    /// <summary>
    /// SQL命令(ling)攔(lan)截器
    /// </summary>
    public class SqlCommandInterceptor : DbCommandInterceptor
    {
        /// <summary>
        /// 讀庫,從庫集群,寫庫不用(yong)設置走默認的EF框(kuang)架
        /// </summary>
        string readConn = System.Configuration.ConfigurationManager.AppSettings["readDb"] ?? string.Empty;
        private string GetReadConn()
        {
            var readArr = readConn.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            var resultConn = string.Empty;
            if (readArr != null && readArr.Any())
            {
                resultConn = readArr[Convert.ToInt32(Math.Floor((double)new Random().Next(0, readArr.Length)))];
            }
            return resultConn;
        }
        //linq to entity生成(cheng)的update,delete
        public override void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
        {
            base.NonQueryExecuting(command, interceptionContext);//update,delete等寫操作直(zhi)接走主庫
        }
        /// <summary>
        /// 執行(xing)sql語句,并(bing)返(fan)(fan)回(hui)第(di)一行(xing)第(di)一列,沒有(you)找到返(fan)(fan)回(hui)null,如果數據庫中值為null,則返(fan)(fan)回(hui) DBNull.Value
        /// </summary>
        /// <param name="command"></param>
        /// <param name="interceptionContext"></param>
        public override void ScalarExecuting(DbCommand command,
           DbCommandInterceptionContext<object> interceptionContext)
        {
            if (!string.IsNullOrWhiteSpace(GetReadConn()))//如果(guo)配置了讀寫分離,就去實(shi)現
            {
                if (!command.CommandText.StartsWith("insert", StringComparison.InvariantCultureIgnoreCase))
                {
                    command.Connection.Close();
                    command.Connection.ConnectionString = GetReadConn();
                    command.Connection.Open();
                }
            }
            base.ScalarExecuting(command, interceptionContext);
        }

        /// <summary>
        /// linq to entity生(sheng)成(cheng)的select,insert
        /// 發(fa)送(song)到sqlserver之前觸發(fa)
        /// warning:在(zai)select語(yu)句中(zhong)DbCommand.Transaction為null,而ef會為每個insert添加(jia)一個DbCommand.Transaction進行包裹
        /// </summary>
        /// <param name="command"></param>
        /// <param name="interceptionContext"&gt;</param>
        public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
        {
            if (!string.IsNullOrWhiteSpace(GetReadConn()))//如果配置了讀寫分離,就(jiu)去實現(xian)
            {
                if (!command.CommandText.StartsWith("insert", StringComparison.InvariantCultureIgnoreCase))
                {
                    command.Connection.Close();
                    command.Connection.ConnectionString = GetReadConn();
                    command.Connection.Open();
                }
            }
            base.ReaderExecuted(command, interceptionContext);
        }
        /// <summary>
        /// 發送到sqlserver之后觸發
        /// </summary>
        /// <param name="command"></param>
        /// <param name="interceptionContext"&gt;</param>
        public override void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
        {
            base.ReaderExecuted(command, interceptionContext);
        }
    }

運(yun)行程序可以設置一些測試代碼

 public ActionResult Index()
        {
            IUnitOfWork db = new backgroundEntities();
            IRepository<WebManageUsers> readUser = new BackgroundRepositoryBase<WebManageUsers>();
            var a = readUser.GetModel().ToList();//讀庫
            using (var trans = new TransactionScope())//事務寫庫
            {
                IRepository<WebManageUsers> userWrite = new BackgroundRepositoryBase<WebManageUsers>(db);
                IRepository<WebManageMenus> menuWrite = new BackgroundRepositoryBase<WebManageMenus>(db);
                var entity = new WebManageUsers
              {
                  WebSystemID = 0,
                  CreateDate = DateTime.Now,
                  DepartmentID = 3,
                  Description = "",
                  Email = "",
                  LoginName = "test",
                  Mobile = "",
                  Operator = "",
                  Password = "",
                  RealName = "test",
                  Status = 1,
                  UpdateDate = DateTime.Now,
              };
                var entity2 = new WebManageMenus
               {
                   ParentID = 1,
                   About = "",
                   LinkUrl = "",
                   MenuLevel = 1,
                   MenuName = "test",
                   Operator = "",
                   SortNumber = 1,
                   Status = 1,
                   UpdateDate = DateTime.Now,
               };
                userWrite.Insert(entity);
                menuWrite.Insert(entity2);
                trans.Complete();
            }



            return View(a);
        }
View Code

最后的(de)(de)結果就是(shi)(shi)我們想要的(de)(de),這里說明一(yi)點,倉(cang)儲大步的(de)(de)讀(du)(du)寫分(fen)離沒有數據(ju)庫(ku)壓力這塊的(de)(de)考(kao)慮,只是(shi)(shi)隨機去訪問某個讀(du)(du)庫(ku)。

回到目錄

posted @ 2015-01-08 14:08  張占嶺  閱讀(4081)  評論(8)    收藏  舉報