Exibições de mapeamento pré-geradas

Antes que o Entity Framework possa executar uma consulta ou salvar alterações na fonte de dados, ele deve gerar um conjunto de exibições de mapeamento para acessar o banco de dados. Essas exibições de mapeamento são um conjunto de instruções SQL de entidade que representam o banco de dados de forma abstrata e fazem parte dos metadados armazenados em cache por domínio do aplicativo. Se você criar várias instâncias do mesmo contexto no mesmo domínio de aplicativo, elas reutilizarão exibições de mapeamento dos metadados armazenados em cache em vez de regenere-las. Como a geração de exibição de mapeamento é uma parte significativa do custo geral da execução da primeira consulta, o Entity Framework permite que você gere visualizações de mapeamento previamente e as inclua no projeto compilado. Para obter mais informações, consulte Considerações de desempenho (Entity Framework).

Gerando exibições de mapeamento com o EF Power Tools Community Edition

A maneira mais fácil de pré-gerar exibições é usar o EF Power Tools Community Edition. Depois de instalar o Power Tools, você terá uma opção de menu para gerar exibições, conforme mostrado abaixo.

  • Para modelos code first , clique com o botão direito do mouse no arquivo de código que contém sua classe DbContext.
  • Para modelos do Designer EF , clique com o botão direito do mouse no arquivo EDMX.

gerar Vistas

Depois que o processo for concluído, você terá uma classe semelhante à seguinte gerada

Exibições geradas

Agora, quando você executar seu aplicativo, o EF usará essa classe para carregar exibições conforme necessário. Se o modelo for alterado e você não gerar novamente essa classe, o EF gerará uma exceção.

Gerando vistas de mapeamento a partir do código – EF6 em diante

A outra maneira de gerar exibições é usar as APIs fornecidas pelo EF. Ao usar esse método, você tem a liberdade de serializar as exibições como quiser, mas também precisa carregar as exibições por conta própria.

Observação

Somente EF6 Em Diante - as APIs mostradas nesta seção foram introduzidas no Entity Framework 6. Se você estiver usando uma versão anterior, essas informações não se aplicarão.

Gerando visualizações

As APIs para gerar exibições estão na classe System.Data.Entity.Core.Mapping.StorageMappingItemCollection. Você pode recuperar um StorageMappingCollection para um contexto usando o MetadataWorkspace de um ObjectContext. Se você estiver usando a API DbContext mais recente, poderá acessá-la usando o IObjectContextAdapter, como abaixo, neste código, temos uma instância de seu DbContext derivado chamada dbContext:

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

Depois de ter o StorageMappingItemCollection, você poderá obter acesso aos métodos GenerateViews e ComputeMappingHashValue.

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

O primeiro método cria um dicionário com uma entrada para cada visão no mapeamento do contêiner. O segundo método calcula um valor de hash para o mapeamento de contêiner único e é usado em runtime para validar que o modelo não foi alterado desde que as exibições foram pré-geradas. As substituições dos dois métodos são fornecidas para cenários complexos envolvendo vários mapeamentos de contêiner.

Ao gerar exibições, você chamará o método GenerateViews e, em seguida, gravará o EntitySetBase e o DbMappingView resultantes. Você também precisará armazenar o hash gerado pelo método ComputeMappingHashValue.

Carregando exibições

Para carregar as exibições geradas pelo método GenerateViews, você pode fornecer ao EF uma classe que herda da classe abstrata DbMappingViewCache. DbMappingViewCache especifica dois métodos que você deve implementar:

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

A propriedade MappingHashValue deve retornar o hash gerado pelo método ComputeMappingHashValue. Quando o EF solicitar exibições, ele primeiro gerará e comparará o valor de hash do modelo com o hash retornado por essa propriedade. Se eles não coincidirem, o EF lançará uma exceção EntityCommandCompilationException.

O método GetView aceitará um EntitySetBase e você precisará retornar um DbMappingView contendo o EntitySql que foi gerado e associado ao EntitySetBase especificado no dicionário gerado pelo método GenerateViews. Se o EF solicitar uma exibição que você não tem, o GetView deverá retornar nulo.

Veja a seguir um extrato do DbMappingViewCache que é gerado com o Power Tools, como descrito acima, no qual vemos uma maneira de armazenar e recuperar o necessário 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");
    }

Para que o EF use seu DbMappingViewCache, você adiciona o DbMappingViewCacheTypeAttribute, especificando o contexto para o qual ele foi criado. No código abaixo, associamos o BlogContext à classe MyMappingViewCache.

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

Para cenários mais complexos, as instâncias de cache de exibição de mapeamento podem ser fornecidas especificando uma fábrica de cache de exibição de mapeamento. Isso pode ser feito implementando a classe abstrata System.Data.Entity.Infrastructure.MappingViews.DbMappingViewCacheFactory. A instância da fábrica de cache de exibição de mapeamento que é usada pode ser recuperada ou definida usando o StorageMappingItemCollection.MappingViewCacheFactoryproperty.