成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

EF Code First:二級緩存

開發 架構
緩存對于一個系統來說至關重要,但是是EF到版本6了仍然沒有見到有支持查詢結果緩存機制的跡象。EF4開始會把查詢語句編譯成存儲過程緩存在Sql Server中,據說EF6中對此做了改進,會把Linq To Entities 的查詢條件直接編譯緩存在EF中。但是這些都是只是對查詢條件做了緩存,而不是緩存查詢的結果集(DbSet.Find(object key)那個雖然走了DbSet.Local數據集,但也僅支持通過主鍵查找單個實體的情況,很有局限性),沒有達到我們想要的效果。

一、前言

今天我們來談談EF的緩存問題。

緩存對于一個系統來說至關重要,但是是EF到版本6了仍然沒有見到有支持查詢結果緩存機制的跡象。EF4開始會把查詢語句編譯成存儲過程緩存在Sql Server中,據說EF6中對此做了改進,會把Linq To Entities 的查詢條件直接編譯緩存在EF中。但是這些都是只是對查詢條件做了緩存,而不是緩存查詢的結果集(DbSet.Find(object key)那個雖然走了DbSet.Local數據集,但也僅支持通過主鍵查找單個實體的情況,很有局限性),沒有達到我們想要的效果。

EF不加緩存功能,可能也有另外的考慮吧,這里不去猜測。雖然EF團隊沒有在EF中加入緩存功能,但已經給出的緩存功能的擴展,這就是Community Entity Framework Provider Wrappers,這個擴展的工作原理由下圖可以清晰的了解:

 該擴展提供了跟蹤SQL運行日志與SQJ結果集緩存的功能,這里,我們只用到它的緩存功能來為EF建立二級緩存的支持。

二、緩存設計

(一) 引用EFProviderWrappers

如下圖,在NuGet中只提供了Entity Framework Provider Wrapper Toolkit(基礎類庫)與Entity Framework Tracing Provider(日志跟蹤)的下載,很遺憾的并沒有提供 Entity Framework Caching Provider(緩存)。

我們只能自己動手來引用了,這里提供幾種思路:

  • 到 http://code.msdn.microsoft.com/EFProviderWrappers 下載代碼,自行編譯,然后在項目GMF.Component.Data項目中手動引用EFProviderWrapperToolkit.dll與EFCachingProvider.dll文件。
  • EFProviderWrapperToolkit由NuGet下載,EFCachingProvider手動引用。

我是覺得兩種思路都挺麻煩的,這個擴展的代碼貌似已經不更新了(3/18/2011),而且在GMF.Component.Data中額外的引用兩個程序集也是個麻煩事,于是我用下面的方法來引用:

在GMF.Component.Data項目中新建兩個文件夾,把以上源代碼中的兩個工程以文件夾的形式包含到項目中。

 

這樣,似乎更干凈利落,如圖:

(二) 緩存代碼分析及整合

1. 關鍵代碼簡介

在EFCachingProvider中,我們要用到的核心類有三個:

  • ICache:緩存緩存基類,系統中實現了一個內存緩存類(InMemoryCache),適用于單臺服務器的緩存實現,如果要實現分布式緩存,可以從這個基類進行擴展。
    • InMemoryCache:內存緩存實現類,內部使用了一個Dictionary<string, CacheEntry>作為緩存容器,以查詢的SQL語句及參數的連接字符串(或其MD5值)為鍵(EFCachingCommands.cs類中定義)。還包含了緩存命中、緩存項數量等數據的統計及緩存清理功能。
  • CachingPolicy:緩存策略基類,定義了當前實體是否可緩存(CanBeCached)、定義緩存緩存數(GetCacheableRows)、緩存項滑動過期與絕對過期時間(GetExpirationTimeout)等功能,并默認了絕對過期時間為永不過期(DateTime.MaxValue)
    • NoCachingPolicy:不緩存策略,禁用緩存功能。
    • CacheAllPolicy:緩存所有數據策略,緩存項最大數量為int.MaxValue
    • CustomCachingPolicy:自定義緩存策略,使用了CacheableTables與NonCacheableTables兩個集合來表示數據類型是否可緩存的白名單與黑名單,這兩個名單將在重寫的CanBeCached方法中作為類型是否可緩存的驗證依據。
  • EFCachingConnection:此類定義了類型為ICache,CachingPolicy的兩個屬性,分別用于接收上面據說的兩個擴展點。

2. 應用緩存擴展

EF的DbContext上下文類有一個重載

public DbContext(DbConnection existingConnection, bool contextOwnsConnection) { }

 

需要的是DbConnection參數,而EFCachingConnection正好是派生自DbConnection的,我們只需要構建一個EFCachingConnection對象作為參數去構造DbContext派生類的對象,即可完成緩存功能的注入(如本篇第一張圖所示)。這里,緩存專用的DbContext派生類只需要派生自原項目中定義的EFDbContext類。

  1. namespace GMF.Component.Data  
  2. {  
  3.     /// <summary>  
  4.     ///     啟用緩存的自定義EntityFramework數據訪問上下文  
  5.     /// </summary>  
  6.     [Export("EFCaching"typeof (DbContext))]  
  7.     public class EFCachingDbContext : EFDbContext  
  8.     {  
  9.         private static readonly InMemoryCache InMemoryCache = new InMemoryCache();  
  10.  
  11.         public EFCachingDbContext()  
  12.             : base(CreateConnectionWrapper("default")) { }  
  13.  
  14.         public EFCachingDbContext(string connectionStringName)  
  15.             : base(CreateConnectionWrapper(connectionStringName)) { }  
  16.  
  17.         /// <summary>  
  18.         ///     由數據庫連接串名稱創建連接對象  
  19.         /// </summary>  
  20.         /// <param name="connectionStringName">數據庫連接串名稱</param>  
  21.         /// <returns></returns>  
  22.         private static DbConnection CreateConnectionWrapper(string connectionStringName)  
  23.         {  
  24.             PublicHelper.CheckArgument(connectionStringName, "connectionStringName");  
  25.  
  26.             string providerInvariantName = "System.Data.SqlClient";  
  27.             string connectionString = null;  
  28.             ConnectionStringSettings connectionStringSetting = ConfigurationManager.ConnectionStrings[connectionStringName];  
  29.             if (connectionStringSetting != null)  
  30.             {  
  31.                 providerInvariantName = connectionStringSetting.ProviderName;  
  32.                 connectionString = connectionStringSetting.ConnectionString;  
  33.             }  
  34.             if (connectionString == null)  
  35.             {  
  36.                 throw PublicHelper.ThrowComponentException("名稱為“" + connectionStringName + "”數據庫連接串的ConnectionString值為空。");  
  37.             }  
  38.             string wrappedConnectionString = "wrappedProvider=" + providerInvariantName + ";" + connectionString;  
  39.             EFCachingConnection connection = new EFCachingConnection  
  40.             {  
  41.                 ConnectionString = wrappedConnectionString,  
  42.                 CachingPolicy = CachingPolicy.CacheAll,  
  43.                 Cache = InMemoryCache  
  44.             };  
  45.  
  46.             return connection;  
  47.         }  
  48.     }  

這里緩存策略使用了緩存所有數據(CacheAllPolicy)的策略,在實際項目中,最好自定義緩存策略,而不要使用這個策略,以免服務器內存被撐爆。

#p#

我們在應用程序配置(Web.Config或App.Config)中,添加一個名為“EntityFrameworkCachingEnabled”的AppSettings節點,用來進行啟用/禁用緩存的開關配置。

  1. <appSettings> 
  2.    ...  
  3.     <add key="EntityFrameworkCachingEnabled" value="true" /> 
  4.    ...  
  5.   </appSettings> 

另外,緩存擴展還需要我們在配置文件中添加如下節點的配置:

  1. <system.data> 
  2.     <DbProviderFactories> 
  3.       <add name="EF Caching Data Provider" invariant="EFCachingProvider" description="Caching Provider Wrapper" type="EFCachingProvider.EFCachingProviderFactory, GMF.Component.Data" /> 
  4.       <add name="EF Generic Provider Wrapper" invariant="EFProviderWrapper" description="Generic Provider Wrapper" type="EFProviderWrapperToolkit.EFProviderWrapperFactory, GMF.Component.Data" /> 
  5.     </DbProviderFactories> 
  6.   </system.data> 

再來看看,怎樣使用“EntityFrameworkCachingEnabled”配置來控制緩存功能的開關。我們的設計中,DbContext對象的注入點為如下所示的Context屬性:

所以,我們只需要在UnitOfWorkContextBase的派生類中讀取 EntityFrameworkCachingEnabled 進行切換即可。

  1. namespace GMF.Component.Data  
  2. {  
  3.     /// <summary>  
  4.     ///     數據單元操作類  
  5.     /// </summary>  
  6.     [Export(typeof (IUnitOfWork))]  
  7.     public class EFRepositoryContext : UnitOfWorkContextBase  
  8.     {  
  9.         /// <summary>  
  10.         ///     獲取 當前使用的數據訪問上下文對象  
  11.         /// </summary>  
  12.         protected override DbContext Context  
  13.         {  
  14.             get 
  15.             {  
  16.                 bool secondCachingEnabled = ConfigurationManager.AppSettings["EntityFrameworkCachingEnabled"].CastTo(false);  
  17.                 return secondCachingEnabled ? EFCachingDbContext.Value : EFDbContext.Value;  
  18.             }  
  19.         }  
  20.  
  21.         [Import("EF"typeof (DbContext))]  
  22.         private Lazy<EFDbContext> EFDbContext { getset; }  
  23.  
  24.         [Import("EFCaching"typeof(DbContext))]  
  25.         private Lazy<EFCachingDbContext> EFCachingDbContext { getset; }  
  26.     }  

注意,因為EFDbContext與EFCachingDbContext兩個屬性只能同時用到其中之一,導入需要使用Lazy<>類型來包裝,這樣沒用到的屬性就不會實例化了。

下面,我們來測試一下緩存功能是否生效,就用上篇的那個翻頁列表吧。判斷標準為SQL Server Profiler是否有SQL語句執行。為方便演示,這里在列表的下方顯示當前的時間,以便與SQL Server Profiler中的時間進行匹配。

 第1頁不計。

點擊第2頁,執行了查詢:

點擊第3頁,執行了查詢:

再回到第2頁,沒有執行查詢:

點擊第4頁,執行了查詢:

結論:重復第2頁的時候,數據已經緩存了,沒有讀數據庫查詢數據,說明緩存已經生效了。

最后要提示的一點:

帶緩存的上下文不能擔當生成數據庫的職責,因此在第一次運行生成數據庫的時候,必須關閉緩存。

 

三、源碼獲取

為了讓大家能第一時間獲取到本架構的最新代碼,也為了方便我對代碼的管理,本系列的源碼已加入微軟的開源項目網站 http://www.codeplex.com,地址為:

https://gmframework.codeplex.com/

原文鏈接:http://www.cnblogs.com/guomingfeng/p/mvc-ef-caching.html

責任編輯:林師授 來源: 博客園
相關推薦

2009-06-18 15:24:35

Hibernate二級

2009-09-21 14:59:31

Hibernate二級

2009-09-24 11:04:56

Hibernate二級

2009-09-21 13:31:10

Hibernate 3

2009-09-21 14:39:40

Hibernate二級

2009-09-23 09:37:07

Hibernate緩存

2025-04-29 07:06:20

2009-06-10 15:00:58

Hibernate二級配置

2013-09-08 22:40:38

EF Code Fir數據查詢架構設計

2013-09-08 21:41:10

RepositoryUnitOfWorkDbContext

2009-08-13 18:12:12

Hibernate 3

2024-12-03 14:38:07

CaffeineRedis二級緩存

2022-03-01 18:03:06

Spring緩存循環依賴

2022-12-02 12:01:30

Spring緩存生命周期

2013-09-08 23:37:30

EF Code Fir架構設計MVC架構設計

2015-06-11 10:12:26

Android圖片加載緩存

2022-01-12 07:48:19

緩存Spring 循環

2023-04-27 08:18:10

MyBatis緩存存儲

2019-08-21 14:34:41

2013-09-08 22:12:02

EF Code Fir數據遷移MVC架構設計
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字幕精品一区二区三区精品 | 色又黄又爽网站www久久 | 黄色亚洲网站 | 亚洲综合伊人 | 日韩免费av | 天天色图 | 亚洲免费视频在线观看 | 艹逼网| 久久久www成人免费精品张筱雨 | 精品视频网 | 日韩中文字幕视频 | 青青久在线视频 | 国产精品欧美一区二区三区不卡 | 一道本不卡视频 | 免费的色网站 | 午夜在线观看视频 | 欧美八区| 色综合久久天天综合网 | 日韩欧美视频 | 国产欧美精品一区 | 成人亚洲一区 | 亚洲精品视频在线播放 | 成人h视频在线 | 成人精品一区亚洲午夜久久久 | 亚洲美女视频 | 日韩欧美国产精品一区 | 精品国产乱码久久久久久老虎 | 精品国产色 | 免费看片国产 | 国产97碰免费视频 | 亚洲激情综合 | 精品美女在线观看视频在线观看 | 成人在线视频免费播放 | 国产精品毛片一区二区在线看 | 极品粉嫩国产48尤物在线播放 | 日韩淫片免费看 | 毛片a级| 亚洲精品一区二区三区蜜桃久 | 国产精品久久久久久久久久东京 | 国产精品日韩在线观看一区二区 | 亚洲精品美女视频 |