Entity Framework 緩存處理與日志監控

作者: 阿不  來源: 博客園  發布時間: 2010-09-01 15:34  閱讀: 18484 次  推薦: 5   原文鏈接   [收藏]  
摘要:在Kooboo中使用了Entity Framework作為持久化框架,但由于EF1.0并沒有提供完整緩存解決方案,一直以來都在為數據緩存而煩腦,現在,EF團隊終于推出一套比較完整的緩存和SQL執行日志的解決方案。

  在Kooboo中使用了Entity Framework作為持久化框架,但由于EF1.0并沒有提供完整緩存解決方案,一直以來都在為數據緩存而煩腦,在沒有找到合適解決方案的情況下,采取了臨時的解決辦法:直接緩存實體。但是由于Entity實體都是帶狀態的,并且都與ObjectContext有間接的反向引用,緩存帶狀態的實體,會造成對象上下文混亂和連接資源的無法被正確釋放。因此緩存的Entity實體,首先必須被分離或者重新定義POCO實體來代替Entity實體作為緩存對象。這樣一來,所有的緩存實體的關聯關系都會失效,造成使用上的麻煩和整個軟件框架存在嚴重的不足。

  再說說EF的SQL日志問題。在之前的LINQ TO SQL的項目中,有一個可視化的調試器,可以查看查詢表達式生成對應的SQL語句,這種可以大大方便開發人員的調試工作。可以在EF1.0中,卻一直也找不到類似可用的工具。因此,我的做法是通過SQL Profile來查看EF生成和執行的SQL語句。雖然可行,但還是很不方便。

  現在,EF團隊終于推出一套比較完整的緩存和SQL執行日志的解決方案,EFProviderWrappers。他們的做法是在原來的EF Provider之上,再加一層包裝,通過這層包裝攔截,進行數據緩存和日志監控。這里緩存的數據是數據庫查詢后返回的原生數據,并不是Entity實體對象,這樣就可以避免Entity實體狀態對緩存造成的的極端負面影響。并且這樣的緩存對上層的數據查詢本身是透明,在同一個封閉區間內,緩存數據所依賴的實體類型在被更新后(對應的表有發生CURD操作),緩存并會被自動清空。對于日志的監控,經過這層包裝后就可以非常容易得到處理。

EfProviderWrapper

  上面的圖雖然是說明對SqlClient有效,但由于這層包裝并不涉及具體的SQL操作,因此對不同的數據的Provider應該都是有效。下面通過一個自帶的實例簡單介紹一下如何使用。

  在下載的EFProviderWrappers解決方案中,EFProviderWrapperToolkit,EFCachingProvider,EFTracingProvider這三個工程是真正干事的,其它的工程都是示例工程。在EFProviderWrapperDemo工程,我們可以找到我們所要的例子。

  第一步:在配置文件中添加如下配置:

 
<system.data>
<DbProviderFactories>
<add name="EF Caching Data Provider"
invariant="EFCachingProvider"
description="Caching Provider Wrapper"
type="EFCachingProvider.EFCachingProviderFactory, EFCachingProvider,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b
" />
<add name="EF Tracing Data Provider"
invariant="EFTracingProvider"
description="Tracing Provider Wrapper"
type="EFTracingProvider.EFTracingProviderFactory, EFTracingProvider,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b
" />
<add name="EF Generic Provider Wrapper"
invariant="EFProviderWrapper"
description="Generic Provider Wrapper"
type="EFProviderWrapperToolkit.EFProviderWrapperFactory, EFProviderWrapperToolkit,
 Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b
" />
</DbProviderFactories>
</system.data>

  第二步:從生成的ObjectContext中繼承一個擴展的ObjectContext,定義所需的擴展屬性,其中重點是重新定義構造器,生成包裝后的EntityConnection對象。

 
public ExtendedNorthwindEntities()
:
this("name=NorthwindEntities")
{
}


public ExtendedNorthwindEntities(string connectionString)
:
base(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(
connectionString,

"EFTracingProvider",
"EFCachingProvider"
))
{
}

  第三步:指定緩存管理器和緩存策略,緩存管理器是可擴展的。默認提供兩種緩存管理器的實現,InMemoryCache和AspNetCache,另外還提供了一種分布式緩存NVelocity適配器的實現:VelocityCache。對于日志監控,可以通過EFTracingProviderConfiguration設置是否輸出到控制臺或輸出到文件,當然通過擴展的ObjectContext還可以將日志輸出到指定的TextWriter:

 
ICache cache = new InMemoryCache();
CachingPolicy cachingPolicy
= CachingPolicy.CacheAll;

// log SQL from all connections to the console
EFTracingProviderConfiguration.LogToConsole = true;

  接下來直接就可以使用,注意不同的ObjectContext實例都要指向同一個ICache實例,并且即使你的創建的ObjectCotnext不需要緩存操作,也應該指定ICache實例,并且設置緩存策略為NoCaching,這樣在當你的ObjectContext調用了SaveChanges后將會自動清空被更新的實體類型的緩存數據。下面一段簡單代碼演示了數據緩存后的SQL執行情況:

 
private static void CacheInvalidationDemo()
{
var cache
= new InMemoryCache();

// log SQL from all connections to the console
EFTracingProviderConfiguration.LogToConsole = true;

for (int i = 0; i < 3; ++i)
{
Console.WriteLine();
Console.WriteLine(
"*** Pass #{0}...", i);
Console.WriteLine();

using (var context = new ExtendedNorthwindEntities())
{

// set up caching
context.Cache = cache;
context.CachingPolicy
= CachingPolicy.CacheAll;

Console.WriteLine(
"Loading customer...");
var cust
= context.Customers.First(c => c.CustomerID == "ALFKI");
Console.WriteLine(
"Customer name: {0}", cust.ContactName);
cust.ContactName
= "Change" + Environment.TickCount;
Console.WriteLine(
"Loading orders...");
cust.Orders.Load();
Console.WriteLine(
"Order count: {0}", cust.Orders.Count);
context.SaveChanges();
}
}

Console.WriteLine();
}

在結果控制臺中你會看第一次執行了SQL,后面兩次都是直接返回結果,并沒有訪問數據庫。

  最后,還想提醒一下,目前下載的這個版本在真正使用時,可能還會存在一些小問題,其中最常見的就是存在大量的throw new NotSupportedException(); 不知出于什么目的并沒有提供這些方法的默認實現,其實只是調用被包裝對象的相應方法而已。

  更多的資源:

  http://blogs.msdn.com/jkowalski/archive/tags/EFProviderWrappers/default.aspx

  http://code.msdn.microsoft.com/EFProviderWrappers

5
2
 
 
 

文章列表

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

    IT工程師數位筆記本

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