Работа с прокси-серверами

При создании экземпляров типов сущностей POCO Entity Framework часто создает экземпляры динамически созданного производного типа, который выступает в качестве прокси-сервера для сущности. Этот прокси переопределяет некоторые виртуальные свойства сущности, чтобы вставить перехватчики для выполнения действий автоматически при доступе к свойству. Например, этот механизм используется для поддержки отложенной загрузки связей. Методы, представленные в этом разделе, также применимы к моделям, созданным с помощью Code First и конструктора EF.

Отключение создания прокси-сервера

Иногда полезно предотвратить создание экземпляров прокси-сервера Entity Framework. Например, сериализация экземпляров, не являющихся прокси-серверами, значительно упрощается, чем сериализация экземпляров прокси-сервера. Создание прокси-сервера можно отключить, очищая ProxyCreationEnabled флаг. Одно место, где это можно сделать, находится в конструкторе контекста. Например:

public class BloggingContext : DbContext
{
    public BloggingContext()
    {
        this.Configuration.ProxyCreationEnabled = false;
    }  

    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
}

Обратите внимание, что EF не будет создавать прокси-серверы для типов, где нет ничего для прокси-сервера. Это означает, что вы также можете избежать прокси-серверов, имея типы, которые запечатаны и (или) не имеют виртуальных свойств.

Явное создание экземпляра прокси-сервера

Экземпляр прокси-сервера не будет создан, если вы создаете экземпляр сущности с помощью нового оператора. Это может не быть проблемой, но если вам нужно создать экземпляр прокси-сервера (например, чтобы отложенная загрузка или отслеживание изменений прокси-сервера работали), то это можно сделать с помощью Create метода DbSet. Например:

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Create();
}

Универсальная версия Create может использоваться, если требуется создать экземпляр производного типа сущности. Например:

using (var context = new BloggingContext())
{
    var admin = context.Users.Create<Administrator>();
}

Обратите внимание, что Create метод не добавляет или присоединяет созданную сущность к контексту.

Обратите внимание, что Create метод просто создаст экземпляр самого типа сущности, если при создании прокси-типа для сущности не будет значения, так как он ничего не сделает. Например, если тип сущности запечатан и (или) не имеет виртуальных свойств, Create то просто создаст экземпляр типа сущности.

Получение фактического типа сущности из типа прокси-сервера

Типы прокси-сервера имеют имена, которые выглядят примерно так:

System.Data.Entity.DynamicProxies.Blog_5E43C6C196972BF0754973E48C9C941092D86818CD94005E9A759B70BF6E48E6

Тип сущности для этого типа прокси-сервера можно найти с помощью GetObjectType метода ObjectContext. Например:

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Find(1);
    var entityType = ObjectContext.GetObjectType(blog.GetType());
}

Обратите внимание, что если переданный GetObjectType тип является экземпляром типа сущности, который не является типом прокси,то тип сущности по-прежнему возвращается. Это означает, что этот метод всегда можно использовать для получения фактического типа сущности без каких-либо других проверка, чтобы узнать, является ли тип прокси-сервера или нет.