Condividi tramite


Viste di mapping pregenerate

Prima che Entity Framework possa eseguire una query o salvare le modifiche all'origine dati, è necessario generare un set di viste di mapping per accedere al database. Queste viste di mapping sono un set di istruzioni Entity SQL che rappresentano il database in modo astratto e fanno parte dei metadati memorizzati nella cache per ogni dominio dell'applicazione. Se si creano più istanze dello stesso contesto nello stesso dominio applicazione, verranno riutilizzate le visualizzazioni di mapping dai metadati memorizzati nella cache anziché rigenerarle. Poiché la generazione di visualizzazioni di mapping è una parte significativa del costo complessivo dell'esecuzione della prima query, Entity Framework consente di pre-generare viste di mapping e includerle nel progetto compilato. Per altre informazioni, vedere Considerazioni sulle prestazioni (Entity Framework).

Generazione di visualizzazioni di mapping con EF Power Tools Community Edition

Il modo più semplice per pre-generare visualizzazioni consiste nell'usare EF Power Tools Community Edition. Dopo aver installato Power Tools, sarà disponibile un'opzione di menu per generare visualizzazioni, come indicato di seguito.

  • Per i modelli Code First fare clic con il pulsante destro del mouse sul file di codice che contiene la classe DbContext.
  • Per i modelli di Ef Designer fare clic con il pulsante destro del mouse sul file EDMX.

generate Views

Al termine del processo, si avrà una classe simile alla seguente generata

generated Views

A questo punto, quando si esegue Entity Framework dell'applicazione userà questa classe per caricare le visualizzazioni in base alle esigenze. Se il modello cambia e non si genera nuovamente questa classe, EF genererà un'eccezione.

Generazione di viste di mapping dal codice - EF6 e versioni successive

L'altro modo per generare visualizzazioni consiste nell'usare le API fornite da Entity Framework. Quando si usa questo metodo si ha la libertà di serializzare le visualizzazioni, ma è anche necessario caricare manualmente le visualizzazioni.

Nota

Solo EF6 e versioni successive: le API illustrate in questa sezione sono state introdotte in Entity Framework 6. Se si usa una versione precedente, queste informazioni non si applicano.

Generazione di visualizzazioni

Le API per generare visualizzazioni si trovano nel mapping system.Data.Entity.Core.Mapping. classe Archiviazione MappingItemCollection. È possibile recuperare un Archiviazione MappingCollection per un contesto usando MetadataWorkspace di un ObjectContext. Se si usa l'API DbContext più recente, è possibile accedervi usando IObjectContextAdapter come illustrato di seguito, in questo codice è disponibile un'istanza del dbContext derivato denominato dbContext:

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

Dopo aver ottenuto il Archiviazione MappingItemCollection, è possibile accedere ai metodi GenerateViews e ComputeMappingHashValue.

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

Il primo metodo crea un dizionario con una voce per ogni visualizzazione nel mapping del contenitore. Il secondo metodo calcola un valore hash per il mapping del singolo contenitore e viene usato in fase di esecuzione per verificare che il modello non sia stato modificato dopo la pre-generazione delle viste. Gli override dei due metodi vengono forniti per scenari complessi che coinvolgono più mapping di contenitori.

Quando si generano visualizzazioni, si chiamerà il metodo GenerateViews e quindi si scriveranno entitySetBase e DbMappingView risultanti. Sarà anche necessario archiviare l'hash generato dal metodo ComputeMappingHashValue.

Caricamento di visualizzazioni

Per caricare le viste generate dal metodo GenerateViews, è possibile fornire a ENTITY Framework una classe che eredita dalla classe astratta DbMappingViewCache. DbMappingViewCache specifica due metodi che è necessario implementare:

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

La proprietà MappingHashValue deve restituire l'hash generato dal metodo ComputeMappingHashValue. Quando EF chiederà le visualizzazioni, verrà prima generato e confrontato il valore hash del modello con l'hash restituito da questa proprietà. Se non corrispondono, Entity EntityCommandCompilationException genererà un'eccezione EntityCommandCompilationException.

Il metodo GetView accetterà un EntitySetBase ed è necessario restituire un oggetto DbMappingVIew contenente EntitySql generato per che è stato associato all'EntitySetBase specificato nel dizionario generato dal metodo GenerateViews. Se EF richiede una visualizzazione che non è disponibile, GetView dovrebbe restituire Null.

Di seguito è riportato un estratto da DbMappingViewCache generato con Power Tools, come descritto in precedenza, in un modo per archiviare e recuperare EntitySql necessario.

    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");
    }

Per fare in modo che Entity Framework usi DbMappingViewCache, devi usare DbMappingViewCacheTypeAttribute, specificando il contesto per cui è stato creato. Nel codice seguente associamo BlogContext alla classe MyMappingViewCache.

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

Per scenari più complessi, è possibile fornire istanze della cache di visualizzazione mapping specificando una factory della cache di visualizzazione mapping. A tale scopo, è possibile implementare la classe astratta System.Data.Entity.Infrastructure.MappingViews.DbMappingViewCacheFactory. L'istanza della factory della cache di visualizzazione mapping utilizzata può essere recuperata o impostata utilizzando il Archiviazione MappingItemCollection.MappingViewCacheFactoryproperty.