ABP中使用Redis Cache(2)


     上一篇講解了如何在ABP中使用Redis Cache,雖然能夠正常的訪問Redis,但是Redis里的信息無法同步更新。本文將講解如何實現Redis Cache與實體同步更新。要實現數據的同步更新,我們能夠想到的最基本、最簡單、也是復雜的方法:在每一個增、刪、改的方法里添加同步緩存的代碼,說它最簡單,是因為技術實現非常簡單,就是在每一個方法里多加一句代碼;說它復雜,是因為這樣的寫的話,會出現很多重復的代碼,並且容易出現遺漏,維護起來很不方便。那么有沒有一種更簡單的方式呢,在數據出現變化后,觸發一個事件,主動通知訂閱者執行相關操作呢?答案是肯定的,我們可以通過注冊領域事件來實現,在ABP中,實體增加、刪除、修改后會觸發相關事件,只要注冊就可以了。要注冊事件,有兩種方式可以實現,第一是自動注冊,實現IEventHandler就可以了,ABP會自動注冊;第二是通過IEventBus的Register方法手動注冊。ABP中推薦使用自動注冊的方式實現,本文也會采用第一種方式實現。下面我們就來看具體的實現方式,首先增加一個處理緩存同步的接口ICacheSyncService,代碼如下(本文的代碼是在上一篇的基礎之上編寫的):

作者:loyldg 出處:http://www.cnblogs.com/loyldg/ 本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接。如有問題,可以郵件:loyldg@126.com 聯系我,非常感謝。

ICacheSyncService.cs

 public interface ICacheSyncService
    {
        void Add<TEntity>(TEntity entity) where TEntity : class, IEntity<int>;
        void Remove<TEntity>(int id) where TEntity : class, IEntity<int>;
        void Update<TEntity>(TEntity entity) where TEntity : class, IEntity<int>;
    }
View Code

CacheSyncService.cs

public class CacheSyncService : ICacheSyncService, ISingletonDependency
    {
        public ICacheService CacheService { get; set; }

        public void Add<TEntity>(TEntity entity) where TEntity : class, IEntity<int>
        {
            CacheService.Set(entity.Id, entity);
        }

        public void Remove<TEntity>(int id) where TEntity : class, IEntity<int>
        {
            CacheService.Remove<int, TEntity>(id);
        }

        public void Update<TEntity>(TEntity entity) where TEntity : class, IEntity<int>
        {
            CacheService.Set(entity.Id, entity);
        }
    }

第二增加一個處理實體事件的泛型基類EntityChangedHandlerBase<TEntity>,代碼如下:

public abstract class EntityChangedHandlerBase<TEntity>:
        ISingletonDependency,
        IEventHandler<EntityCreatedEventData<TEntity>>,
        IEventHandler<EntityDeletedEventData<TEntity>>,
        IEventHandler<EntityUpdatedEventData<TEntity>>
        where TEntity : class, IEntity<int>
    {
        public ICacheSyncService CacheSyncService { get; set; }

        public virtual void HandleEvent(EntityCreatedEventData<TEntity> eventData)
        {
            CacheSyncService.Add(eventData.Entity);
        }

        public virtual void HandleEvent(EntityDeletedEventData<TEntity> eventData)
        {
            CacheSyncService.Remove<TEntity>(eventData.Entity.Id);
        }

        public virtual void HandleEvent(EntityUpdatedEventData<TEntity> eventData)
        {
            CacheSyncService.Update(eventData.Entity);
        }
    }

第三,增加一個需要進行緩存同步的實體類,繼承自EntityChangedHandlerBase<TEntity>就可以了,不需要編寫任何代碼,如果有特殊情況,可以重新HandleEvent方法,代碼如下:

public class ArticleChangedHandler : EntityChangedHandlerBase<Article>
    {
        
    }
View Code

至此,緩存同步的全部代碼已編寫完成,我們運行來看看效果:

我們添加文章后,什么操作也不做,直接到Redis里查看是否有新增的數據,如果有新增的數據表示緩存能夠自動更新了(刪除和修改是一樣的,這里就不編寫相關代碼了),直接看單元測試代碼。

public class CacheSync_Tests : UsingRedisInAbpTestBase
    {
         [Fact]
        public void Test_Entity_Changed_Event()
        {
             LoginAsHostAdmin();
             var title = "unit_test";
             var articleId = 0;
             var service = Resolve<TestCacheSyncService>();
             service.IsCreatedEventFired.ShouldBeFalse();
             service.IsUpdatedEventFired.ShouldBeFalse();
             service.IsDeletedEventFired.ShouldBeFalse();
             
             //新增文章測試
             UsingDbContext(c =>c.Articles.Add(new Article {Title = title}));
             
             service.IsCreatedEventFired.ShouldBe(true);

             //更新文章測試
             UsingDbContext(c =>
             {
                 var article=c.Articles.First();
                 c.Articles.Attach(article);
                 article.Title = "new_title";
             });
             service.IsUpdatedEventFired.ShouldBe(true);

             //刪除文章測試
             UsingDbContext(c =>
             {
                 var article = c.Articles.First();
                 c.Articles.Remove(article);                 
             });
             service.IsDeletedEventFired.ShouldBe(true);
        }
    }

TestSyncCache.cs代碼:

 public class TestCacheSyncService : ICacheSyncService
    {
        public bool IsCreatedEventFired { get; set; }
        public bool IsDeletedEventFired { get; set; }
        public bool IsUpdatedEventFired { get; set; }
        public void Add<TEntity>(TEntity entity) where TEntity : class, IEntity<int>
        {
            IsCreatedEventFired = true;
            
        }

        public void Remove<TEntity>(int id) where TEntity : class, IEntity<int>
        {
            IsDeletedEventFired = true;

        }

        public void Update<TEntity>(TEntity entity) where TEntity : class, IEntity<int>
        {
            IsUpdatedEventFired = true;
        }
    }  
View Code

通過以上方式已實現了ABP中Redis緩存的讀取和設置,也實現了緩存的同步更新,如果要在ABP中使用其他緩存也是一樣的,只需要把緩存實現部分換成其他緩存就行。本文的所有源代碼下載地址:

http://files.cnblogs.com/files/loyldg/UsingRedisInAbp_2.src.rar

作者:loyldg 出處:http://www.cnblogs.com/loyldg/ 本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接。如有問題,可以郵件:loyldg@126.com 聯系我,非常感謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM