Предварительно созданные представления сопоставления

Прежде чем Entity Framework может выполнить запрос или сохранить изменения в источнике данных, он должен создать набор представлений сопоставления для доступа к базе данных. Эти представления сопоставления являются набором инструкции Entity SQL, представляющей базу данных абстрактным образом, и являются частью метаданных, кэшируемых для каждого домена приложения. При создании нескольких экземпляров одного контекста в одном домене приложения они будут повторно использовать представления сопоставления из кэшированных метаданных, а не повторно создавать их. Поскольку создание представления сопоставления является значительной частью общей стоимости выполнения первого запроса, Entity Framework позволяет предварительно создавать представления сопоставления и включать их в скомпилированный проект. Дополнительные сведения см. в разделе "Рекомендации по производительности" (Entity Framework).

Создание представлений сопоставления с помощью EF Power Tools Community Edition

Самый простой способ предварительного создания представлений — использовать EF Power Tools Community Edition. После установки Power Tools у вас будет пункт меню для создания представлений, как показано ниже.

  • Для моделей Code First щелкните правой кнопкой мыши файл кода, содержащий класс DbContext.
  • Для моделей EF Designer щелкните правой кнопкой мыши файл EDMX.

generate Views

После завершения процесса у вас будет класс, аналогичный приведенному ниже.

generated Views

Теперь, когда вы запускаете приложение EF, будет использовать этот класс для загрузки представлений по мере необходимости. Если модель изменяется, и вы не создаете этот класс повторно, EF вызовет исключение.

Создание представлений сопоставления из кода — EF6 Onwards

Другим способом создания представлений является использование API, которые предоставляет EF. При использовании этого метода у вас есть свобода сериализации представлений, как вам нравится, но вам также нужно загрузить представления самостоятельно.

Примечание.

Ef6 Onwards Only — API, показанные в этом разделе, были представлены в Entity Framework 6. Если вы используете более раннюю версию, эта информация не применяется.

Создание представлений

API-интерфейсы для создания представлений находятся в System.Data.Entity.Core.Mapping. класс служба хранилища MappingItemCollection. Вы можете получить служба хранилища MappingCollection для контекста с помощью пространства метаданных объекта ObjectContext. Если вы используете более новый API DbContext, вы можете получить доступ к этому с помощью IObjectContextAdapter, как показано ниже, в этом коде есть экземпляр производного DbContext с именем dbContext:

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

Получив служба хранилища MappingItemCollection, вы можете получить доступ к методам GenerateViews и ComputeMappingHashValue.

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

Первый метод создает словарь с записью для каждого представления в сопоставлении контейнеров. Второй метод вычисляет хэш-значение для сопоставления одного контейнера и используется во время выполнения для проверки того, что модель не изменилась, так как представления были предварительно созданы. Переопределения двух методов предоставляются для сложных сценариев, связанных с несколькими сопоставлениями контейнеров.

При создании представлений необходимо вызвать метод GenerateViews, а затем записать результирующий Объект EntitySetBase и DbMappingView. Кроме того, необходимо сохранить хэш, созданный методом ComputeMappingHashValue.

Загрузка представлений

Чтобы загрузить представления, созданные методом GenerateViews, можно предоставить EF класс, наследуемый от абстрактного класса DbMappingViewCache. DbMappingViewCache указывает два метода, которые необходимо реализовать:

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

Свойство MappingHashValue должно возвращать хэш, созданный методом ComputeMappingHashValue. Когда EF будет запрашивать представления, он сначала создаст и сравнивает хэш-значение модели с хэшом, возвращаемым этим свойством. Если они не соответствуют, EF вызовет исключение EntityCommandCompilationException.

Метод GetView принимает EntitySetBase, и необходимо вернуть dbMappingVIew, содержащий EntitySql, созданный для этого объекта EntitySetBase, в словаре, созданном методом GenerateViews. Если EF запрашивает представление, которое у вас нет, GetView должен возвращать значение NULL.

Ниже приведено извлечение из DbMappingViewCache, созданного с помощью Power Tools, как описано выше, в нем мы видим один из способов хранения и получения требуемого Объекта 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");
    }

Чтобы использовать EF dbMappingViewCache, вы добавляете dbMappingViewCacheTypeAttribute, указав контекст, для который он был создан. В приведенном ниже коде мы свяжите BlogContext с классом MyMappingViewCache.

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

Для более сложных сценариев можно предоставить экземпляры кэша представления сопоставления, указав фабрику кэша представления сопоставления. Это можно сделать, реализуя абстрактный класс System.Data.Entity.Infrastructure.MappingViews.DbMappingViewCacheFactory. Экземпляр фабрики кэша представления сопоставления, который используется, можно получить или задать с помощью служба хранилища MappingItemCollection.MappingViewCacheFactoryproperty.