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 do Entity SQL 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 sobre Desempenho (Entity Framework).
Como gerar 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 do 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 do EF, clique com o botão direito do mouse no arquivo EDMX.
Depois que o processo for concluído, você terá uma classe semelhante à seguinte gerada
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.
Como gerar exibições de mapeamento 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 a partir do EF6: as APIs mostradas nessa seção foram introduzidas no Entity Framework 6. Se você estiver usando uma versão anterior, algumas ou todas essas informações não se aplicarão.
Geração de exibiçõ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, nesse 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);
Quando você tiver 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 exibição no mapeamento de 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.
Como carregando modos de exibição
Para carregar os modos de exibição gerados 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 corresponderem, 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 para o qual foi associado ao EntitySetBase especificado no dicionário gerado pelo método GenerateViews. Se o EF solicitar um modo de exibição que você não tem, o GetView deverá retornar nulo.
Veja a seguir um trecho do DbMappingViewCache que é gerado com as Ferramentas Elétricas, conforme descrito acima, nele vemos uma maneira de armazenar e recuperar o EntitySql necessário.
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 use 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.