預先產生的對應檢視
在 Entity Framework 可以執行查詢或儲存資料來源的變更之前,它必須產生一組對應檢視來存取資料庫。 這些對應檢視是一組 Entity SQL 語句,以抽象方式表示資料庫,而且是每個應用程式域快取之中繼資料的一部分。 如果您在相同的應用程式域中建立相同內容的多個實例,它們會重複使用快取中繼資料中的對應檢視,而不是重新產生它們。 因為對應檢視產生是執行第一個查詢整體成本的重要部分,Entity Framework 可讓您預先產生對應檢視,並將其包含在編譯的專案中。 如需詳細資訊,請參閱 效能考慮(Entity Framework)。
使用 EF Power Tools Community Edition 產生對應檢視
預先產生檢視的最簡單方式是使用 EF Power Tools Community Edition 。 安裝 Power Tools 之後,您將有 [產生檢視] 的功能表選項,如下所示。
- 針對 Code First 模型,以滑鼠右鍵按一下包含 DbCoNtext 類別的程式碼檔案。
- 針對 EF Designer 模型,以滑鼠右鍵按一下您的 EDMX 檔案。
程式完成之後,您將會有類似下列產生的類別
現在當您執行應用程式 EF 時,會使用此類別視需要載入檢視。 如果您的模型變更,且您未重新產生此類別,EF 將會擲回例外狀況。
從程式碼產生對應檢視 - EF6 及更新版本
產生檢視的另一種方式是使用 EF 提供的 API。 使用此方法時,您可以隨意序列化檢視,但也需要自行載入檢視。
注意
僅限 EF6 及更新版本 - 本節中顯示的 API 是在 Entity Framework 6 中引進的。 如果您使用舊版,則不適用這項資訊。
產生檢視
要產生檢視的 API 位於 System.Data.Entity.Core.Mapping 上。儲存體MappingItemCollection 類別。 您可以使用 ObjectCoNtext 的 MetadataWorkspace 來擷取 CoNtext 的 儲存體MappingCollection。 如果您使用較新的 DbCoNtext API,則可以使用如下的 IObjectCoNtextAdapter 來存取此 API,在此程式碼中,我們有一個稱為 dbCoNtext 的衍生 DbCoNtext 實例:
var objectContext = ((IObjectContextAdapter) dbContext).ObjectContext;
var mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace
.GetItemCollection(DataSpace.CSSpace);
取得 儲存體MappingItemCollection 之後,您就可以存取 GenerateViews 和 ComputeMappingHashValue 方法。
public Dictionary<EntitySetBase, DbMappingView> GenerateViews(IList<EdmSchemaError> errors)
public string ComputeMappingHashValue()
第一個方法會建立字典,其中包含容器對應中每個檢視的專案。 第二種方法會計算單一容器對應的雜湊值,並在執行時間用來驗證模型自預先產生檢視後尚未變更。 針對涉及多個容器對應的複雜案例,會提供這兩種方法的覆寫。
產生檢視時,您將呼叫 GenerateViews 方法,然後寫出產生的 EntitySetBase 和 DbMappingView。 您也需要儲存 ComputeMappingHashValue 方法所產生的雜湊。
載入檢視
若要載入 GenerateViews 方法所產生的檢視,您可以為 EF 提供繼承自 DbMappingViewCache 抽象類別的類別。 DbMappingViewCache 指定兩種方法,您必須實作:
public abstract string MappingHashValue { get; }
public abstract DbMappingView GetView(EntitySetBase extent);
MappingHashValue 屬性必須傳回 ComputeMappingHashValue 方法所產生的雜湊。 當 EF 要求檢視時,它會先產生模型雜湊值,並將其與這個屬性所傳回的雜湊進行比較。 如果它們不相符,EF 會擲回 EntityCommandCompilationException 例外狀況。
GetView 方法會接受 EntitySetBase,而您需要傳回 DbMappingVIew,其中包含針對該物件所產生的 EntitySql,與 GenerateViews 方法所產生字典中給定 EntitySetBase 相關聯的 DbMappingVIew。 如果 EF 要求您沒有的檢視,GetView 應該會傳回 null。
以下是使用上述 Power Tools 產生的 DbMappingViewCache 擷取,其中我們看到儲存和擷取 EntitySql 所需的其中一種方式。
public override string MappingHashValue
{
get { return "a0b843f03dd29abee99789e190a6fb70ce8e93dc97945d437d9a58fb8e2afd2e"; }
}
public override DbMappingView GetView(EntitySetBase extent)
{
if (extent == null)
{
throw new ArgumentNullException("extent");
}
var extentName = extent.EntityContainer.Name + "." + extent.Name;
if (extentName == "BlogContext.Blogs")
{
return GetView2();
}
if (extentName == "BlogContext.Posts")
{
return GetView3();
}
return null;
}
private static DbMappingView GetView2()
{
return new DbMappingView(@"
SELECT VALUE -- Constructing Blogs
[BlogApp.Models.Blog](T1.Blog_BlogId, T1.Blog_Test, T1.Blog_title, T1.Blog_Active, T1.Blog_SomeDecimal)
FROM (
SELECT
T.BlogId AS Blog_BlogId,
T.Test AS Blog_Test,
T.title AS Blog_title,
T.Active AS Blog_Active,
T.SomeDecimal AS Blog_SomeDecimal,
True AS _from0
FROM CodeFirstDatabase.Blog AS T
) AS T1");
}
若要讓 EF 使用您的 DbMappingViewCache,請新增使用 DbMappingViewCacheTypeAttribute,並指定其建立的內容。 在下列程式碼中,我們會將 BlogCoNtext 與 MyMappingViewCache 類別產生關聯。
[assembly: DbMappingViewCacheType(typeof(BlogContext), typeof(MyMappingViewCache))]
針對更複雜的案例,您可以藉由指定對應檢視快取處理站來提供對應檢視快取實例。 這可以藉由實作抽象類別 System.Data.Entity.Infrastructure.MappingViews.DbMappingViewCacheFactory 來完成。 您可以使用 儲存體MappingItemCollection.MappingViewCacheFactoryproperty 來擷取或設定所使用的對應檢視快取處理站實例。