文章出處

回到目錄

Redis本身支持事務,這就是SQL數據庫有Transaction一樣,而Redis的驅動也支持事務,這在ServiceStack.Redis就有所體現,它也是目前最受業界認可的Redis驅動,而它將Redis的事務機制(MULTI,Exec,Watch等)封裝成了比較友好的實現方式,如下面的代碼

    using (IRedisClient RClient = prcm.GetClient())
    {
      using (IRedisTransaction IRT = RClient.CreateTransaction())
        {
            IRT.QueueCommand(r => r.AddItemToList("zzl", "2"));
            IRT.QueueCommand(r => r.AddItemToList("lr", "2")); IRT.Commit();
// 提交事務 } }

當然上面漂亮的代碼有一些功勞要歸于C#漂亮的語法,你在JAVA里可以很難寫出如此漂亮的東西,當然上面的代碼是ServiceStack.Redis為我們封裝的,平時我們可以直接使用,現在再說一下大叔Lind.DDD框架里的RedisRepository對它的支持!

如果大叔RedisRepository想支持redis事務,前提:倉儲的IRedisClient必須與產生事務的IRedisClient是同一個對象,否則redis事務在大叔框架里不會起作用

實現方法:

一  RedisRepository<T>實現SetDataContext方法,將IRedisClient從外面傳入,這樣可以保存事務的和倉儲的用的是一個對象

      public void SetDataContext(object db)
        {
            try
            {
                //手動Redis數據庫對象,在redis事務時啟用
                redisDB = (IRedisClient)db;
                redisTypedClient = redisDB.GetTypedClient<TEntity>();
                table = redisTypedClient.Lists[typeof(TEntity).Name];
            }
            catch (Exception)
            {

                throw new ArgumentException("redis.SetDataContext要求db為IRedisClient類型");
            }

        }

二 添加基于Redis的事務管理者,讓大叔倉儲與事務更好的結合,方便開發人員的使用

    /// <summary>
    /// Redis事務管理機制
    /// </summary>
    public class RedisTransactionManager
    {
        /// <summary>
        /// 事務塊處理
        /// </summary>
        /// <param name="redisClient">當前redis庫</param>
        /// <param name="action">事務中的動作</param>
        public static void Transaction(IRedisClient redisClient, Action action)
        {
            using (IRedisTransaction IRT = redisClient.CreateTransaction())
            {
                try
                {
                    action();
                    IRT.Commit();
                }
                catch (Exception)
                {
                    IRT.Rollback();
                }
            }
        }

    }

三 在領域代碼中,我們通常可以這樣使用大叔redis的事務塊,看代碼

            var redis = new Lind.DDD.Repositories.Redis.RedisRepository<User>();
            IRedisClient redisClient = Lind.DDD.RedisClient.RedisManager.GetClient();
            redis.SetDataContext(redisClient);
            Lind.DDD.RedisClient.RedisTransactionManager.Transaction(redisClient, () =>
            {
                redis.Insert(new User { UserName = "gogod111" });
                redis.Insert(new User { UserName = "gogod211" });
            });

這樣,大叔框架就支持了Redis的事務,希望MongoDB早日也能對事務進行支持,到那時,大叔將會為它提供一種實現機制,呵呵!

下面是大叔對分布式多數據源事務的測試,可以實現SQLSERVER與Redis的事務共存機制,下面是代碼

           Lind.DDD.RedisClient.RedisTransactionManager.Transaction(redisClient, () =>
            {
                redis.Insert(new User { UserName = "gogod111" });
                redis.Insert(new User { UserName = "gogod211" });

                using (var trans = new TransactionScope())
                {
                    userRepository.Insert(new UserInfo { UserName = "zzl3" });
                    trans.Complete();
                }
            });

上面代碼我們還能進行一些封裝,一些修改,讓它支持redis和sql兩種事務,使用.net4.5的默認參數,可以省去一個方法的重載,代碼又便得越來越簡潔了!

        /// <summary>
        /// 事務塊處理
        /// </summary>
        /// <param name="redisClient">當前redis庫</param>
        /// <param name="redisAction">Redis事務中的動作</param>
        /// <param name="sqlAction">Sql事務中的動作</param>
        public static void Transaction(IRedisClient redisClient, Action redisAction, Action sqlAction = null)
        {
            using (IRedisTransaction IRT = redisClient.CreateTransaction())
            {
                try
                {
                    redisAction();
                    if (sqlAction != null)
                    {
                        using (var trans = new TransactionScope())
                        {
                            sqlAction();
                            trans.Complete();
                        }
                    }
                    IRT.Commit();
                }
                catch (Exception)
                {
                    IRT.Rollback();
                }
            }
        }

代碼在調用時,我們很方便,簡單!

           Lind.DDD.RedisClient.RedisTransactionManager.Transaction(redisClient, () =>
            {
                redis.Insert(new User { UserName = "gogod111" });
                redis.Insert(new User { UserName = "gogod211" });
            }, () =>
            {
                userRepository.Insert(new UserInfo { UserName = "zzl3" });
            });

對于C#代碼團隊的不段進步,也是我們這些程序員喜愛它的原因之一,畢竟人都有個膩的時候,多多改善,對自己,對他人都是件不錯好事!

回到目錄


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()