Compartir a través de


Vistas de asignación generadas previamente

Antes de que Entity Framework pueda ejecutar una consulta o guardar los cambios realizados en el origen de datos, debe generar un conjunto de vistas de asignación para obtener acceso a la base de datos. Estas vistas de asignación son un conjunto de instrucciones Entity SQL que representan la base de datos de forma abstracta y forman parte de los metadatos que se almacenan en caché por cada dominio de aplicación. Si crea varias instancias del mismo contexto del objeto en el mismo dominio de aplicación, volverán a usar las vistas de asignación de los metadatos almacenados en caché en lugar de volver a generarlos. Dado que la generación de vistas de asignación forma parte en gran medida del costo total que supone ejecutar la primera consulta, Entity Framework permite generar previamente estas vistas e incluirlas en el proyecto compilado. Para obtener más información, consulte Consideraciones sobre el rendimiento (Entity Framework).

Generación de vistas de asignación con EF Power Tools Community Edition

La manera más fácil de generar vistas previamente es usar EF Power Tools Community Edition. Una vez que tenga instalado Power Tools, tendrá una opción de menú para generar vistas, de la manera siguiente.

  • En los modelos Code First, haga clic con el botón derecho en el archivo de código que contiene la clase DbContext.
  • En los modelos EF Designer, haga clic con el botón derecho en el archivo EDMX.

generate Views

Una vez finalizado el proceso, habrá generado una clase similar a la siguiente.

generated Views

Ahora, cuando ejecute la aplicación, EF usará esta clase para cargar vistas según sea necesario. Si el modelo cambia y no vuelve a generar esta clase, EF producirá una excepción.

Generación de vistas de asignación a partir del código: EF6 y versiones posteriores

La otra manera de generar vistas es usar las API que proporciona EF. Al usar este método, tiene la libertad de serializar las vistas, pero también debe cargarlas por su cuenta.

Nota:

Solo EF6 y versiones posteriores: las API mostradas en esta sección se introdujeron en Entity Framework 6. Si usa una versión anterior, esta información no se aplica.

Generar vistas

Las API para generar vistas se encuentran en la clase System.Data.Entity.Core.Mapping.StorageMappingItemCollection. Puede recuperar un objeto StorageMappingCollection para un contexto mediante el objeto MetadataWorkspace de un objeto ObjectContext. Si usa la API DbContext más reciente, puede acceder a ella mediante IObjectContextAdapter como se muestra a continuación. En este código tenemos una instancia de dbContext derivada llamada dbContext:

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

Una vez que tenga el objeto StorageMappingItemCollection, puede obtener acceso a los métodos GenerateViews y ComputeMappingHashValue.

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

El primer método crea un diccionario con una entrada para cada vista de la asignación de contenedores. El segundo método calcula un valor hash para la asignación de un solo contenedor y se usa en tiempo de ejecución para validar que el modelo no ha cambiado desde que se generaron previamente las vistas. Se proporcionan invalidaciones de los dos métodos para escenarios complejos que implican varias asignaciones de contenedores.

Al generar vistas, llamará al método GenerateViews y, luego, escribirá los objetos EntitySetBase y DbMappingView resultantes. También deberá almacenar el hash generado por el método ComputeMappingHashValue.

Carga de las vistas

Para cargar las vistas generadas por el método GenerateViews, puede proporcionar a EF una clase que herede de la clase abstracta DbMappingViewCache. DbMappingViewCache especifica dos métodos que debe implementar:

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

La propiedad MappingHashValue debe devolver el hash generado por el método ComputeMappingHashValue. Cuando EF vaya a pedir vistas, primero generará y comparará el valor hash del modelo con el hash devuelto por esta propiedad. Si no coinciden, EF iniciará una excepción EntityCommandCompilationException.

El método GetView aceptará un objeto EntitySetBase y deberá devolver un objeto DbMappingVIew que contenga el objeto EntitySql que se generó para que se asociara con el objeto EntitySetBase dado en el diccionario generado por el método GenerateViews. Si EF solicita una vista que no tiene, GetView devolverá null.

A continuación se muestra un extracto del objeto DbMappingViewCache que se genera con Power Tools como se ha descrito anteriormente. En él podemos ver una manera de almacenar y recuperar el objeto EntitySql requerido.

    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 EF use su objeto DbMappingViewCache, agregue el objeto DbMappingViewCacheTypeAttribute y especifique el contexto para el que se creó. En el código siguiente, asociamos BlogContext a la clase MyMappingViewCache.

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

En el caso de escenarios más complejos, se pueden proporcionar instancias de caché de vistas de asignación especificando una fábrica de cachés de vistas de asignación. Para ello, implemente la clase abstracta System.Data.Entity.Infrastructure.MappingViews.DbMappingViewCacheFactory. La instancia de la fábrica de cachés de vistas de asignación que se usa se puede recuperar o establecer mediante la propiedad StorageMappingItemCollection.MappingViewCacheFactory.