Wstępnie wygenerowane widoki mapowania

Zanim program Entity Framework będzie mógł wykonać zapytanie lub zapisać zmiany w źródle danych, musi wygenerować zestaw widoków mapowania w celu uzyskania dostępu do bazy danych. Te widoki mapowania są zestawem instrukcji Entity SQL, które reprezentują bazę danych w sposób abstrakcyjny i są częścią metadanych, które są buforowane dla domeny aplikacji. Jeśli utworzysz wiele wystąpień tego samego kontekstu w tej samej domenie aplikacji, będą ponownie używać widoków mapowania z buforowanych metadanych, a nie ich ponownego generowania. Ponieważ generowanie widoku mapowania jest znaczącą częścią ogólnego kosztu wykonywania pierwszego zapytania, platforma Entity Framework umożliwia wstępne generowanie widoków mapowania i uwzględnianie ich w skompilowanym projekcie. Aby uzyskać więcej informacji, zobacz Zagadnienia dotyczące wydajności (Entity Framework).

Generowanie widoków mapowania za pomocą programu EF Power Tools Community Edition

Najprostszym sposobem wstępnego generowania widoków jest użycie programu EF Power Tools Community Edition. Po zainstalowaniu narzędzi Power Tools będzie dostępna opcja menu Generuj widoki, jak pokazano poniżej.

  • Dla modeli Code First kliknij prawym przyciskiem myszy plik kodu zawierający klasę DbContext.
  • W przypadku modeli programu EF Designer kliknij prawym przyciskiem myszy plik EDMX.

generowanie widoków

Po zakończeniu procesu będziesz mieć klasę podobną do następującej wygenerowanej

wygenerowane widoki

Teraz, gdy uruchomisz aplikację EF, użyjesz tej klasy do załadowania widoków zgodnie z potrzebami. Jeśli model ulegnie zmianie i nie wygenerujesz ponownie tej klasy, program EF zgłosi wyjątek.

Generowanie widoków mapowania z kodu: od EF6 i nowsze

Innym sposobem generowania widoków jest użycie interfejsów API zapewnianych przez platformę EF. W przypadku korzystania z tej metody masz swobodę serializacji widoków, ale musisz również załadować widoki samodzielnie.

Uwaga / Notatka

Tylko od EF6: interfejsy API pokazane w tej sekcji zostały wprowadzone w wersji Entity Framework 6. Jeśli używasz starszej wersji, te informacje nie mają zastosowania.

Generowanie widoków

API do generowania widoków znajdują się w klasie System.Data.Entity.Core.Mapping.StorageMappingItemCollection. Kolekcję StorageMappingCollection dla kontekstu można pobrać za pomocą MetadataWorkspace obiektu ObjectContext. Jeśli używasz nowszego interfejsu API DbContext, możesz uzyskać do niego dostęp przy użyciu obiektu IObjectContextAdapter, jak pokazano poniżej, w tym kodzie mamy wystąpienie pochodnego obiektu DbContext o nazwie dbContext:

    var objectContext = ((IObjectContextAdapter) dbContext).ObjectContext;
    var  mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace
                                                                        .GetItemCollection(DataSpace.CSSpace);

Po utworzeniu kolekcji StorageMappingItemCollection możesz uzyskać dostęp do metod GenerateViews i ComputeMappingHashValue.

    public Dictionary<EntitySetBase, DbMappingView> GenerateViews(IList<EdmSchemaError> errors)
    public string ComputeMappingHashValue()

Pierwsza metoda tworzy słownik z wpisem dla każdego widoku w mapowaniu kontenera. Druga metoda oblicza wartość skrótu dla pojedynczego mapowania kontenera i jest używana w czasie wykonywania w celu sprawdzenia, czy model nie uległ zmianie od czasu wstępnego wygenerowania widoków. Zastąpienia tych dwóch metod są udostępniane dla złożonych scenariuszy obejmujących wiele mapowań kontenerów.

Podczas generowania widoków wywołasz metodę GenerateViews, a następnie zapiszesz wynikowe obiekty EntitySetBase i DbMappingView. Należy również przechowywać skrót wygenerowany przez metodę ComputeMappingHashValue.

Ładowanie widoków

Aby załadować widoki wygenerowane przez metodę GenerateViews, możesz dostarczyć EF klasę, która dziedziczy po abstrakcyjnej klasie DbMappingViewCache. DbMappingViewCache określa dwie metody, które należy zaimplementować:

    public abstract string MappingHashValue { get; }
    public abstract DbMappingView GetView(EntitySetBase extent);

Właściwość MappingHashValue musi zwrócić skrót wygenerowany przez metodę ComputeMappingHashValue. Gdy program EF zapyta o widoki, najpierw wygeneruje i porówna wartość hashu modelu z wartością hashu zwróconą przez tę właściwość. Jeśli nie są one zgodne, program EF zgłosi wyjątek EntityCommandCompilationException.

Metoda GetView przyjmie parametr EntitySetBase i musi zwrócić obiekt DbMappingView zawierający EntitySql, który został wygenerowany dla skojarzonego z nim EntitySetBase w słowniku utworzonym przez metodę GenerateViews. Jeśli program EF prosi o widok, którego nie masz, polecenie GetView powinno zwrócić wartość null.

Poniżej przedstawiono wyodrębnienie z obiektu DbMappingViewCache wygenerowanego za pomocą narzędzi Power Tools zgodnie z powyższym opisem. W nim widzimy jeden ze sposobów przechowywania i pobierania wymaganej składni 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");
    }

Aby platforma EF korzystała z obiektu DbMappingViewCache, należy dodać element DbMappingViewCacheTypeAttribute, określając kontekst, dla którego został utworzony. W poniższym kodzie skojarzymy element BlogContext z klasą MyMappingViewCache.

    [assembly: DbMappingViewCacheType(typeof(BlogContext), typeof(MyMappingViewCache))]

W przypadku bardziej złożonych scenariuszy wystąpienia pamięci podręcznej widoku mapowania mogą być udostępniane przez określenie fabryki pamięci podręcznej widoku mapowania. Można to zrobić, implementując abstrakcyjną klasę System.Data.Entity.Infrastructure.MappingViews.DbMappingViewCacheFactory. Wystąpienie używanej fabryki pamięci podręcznej widoku mapowania można pobrać lub ustawić przy użyciu właściwości StorageMappingItemCollection.MappingViewCacheFactory property.