Подтвердить что ты не робот

Получить базовый объект сущности из прокси-сервера сущностей

У меня есть объект, получая его от DbEntityEntry.Entity. Это возвращает прокси-объект Entity Framework для объекта.

Как мне получить доступ к базовому объекту как к исходному типу, а не к прокси?

В качестве альтернативы мне нужно динамически попытаться применить прокси к типу сущности. Вот начало...

var theEntityType = entityEntry.Entity;

if (theEntityType.BaseType != null && entityType.Namespace == "System.Data.Entity.DynamicProxies")
       theEntityType = entityType.BaseType;

// Now I need to cast to the correct type
var entityObject = (theEntityType)entityEntry.Entity; // THIS WON'T WORK BECAUSE `theEntityType` is dynamic.
// My entites also don't implement IConvertible
4b9b3361

Ответ 1

Сначала я должен сказать, что нет основного объекта. Прокси не переносит объект сущности (шаблон декоратора), он вытекает из него (наследование). Таким образом, мы не можем развернуть объект, мы можем преобразовать прокси-сервер в базовый объект. Преобразование (вопреки кастингу) всегда создает новый объект.

Для этого преобразования мы можем использовать тот факт, что большую часть времени, кстати, прокси-серверы возвращаются EF, тип времени компиляции прокси-сервера является базовым. То есть, если прокси вводится в качестве аргумента в общий метод, общий параметр будет выведен в качестве базового типа. Эта функция позволяет нам создать метод, который делает то, что вы хотите:

T UnProxy<T>(DbContext context, T proxyObject) where T : class
{
    var proxyCreationEnabled = context.Configuration.ProxyCreationEnabled;
    try
    {
        context.Configuration.ProxyCreationEnabled = false;
        T poco = context.Entry(proxyObject).CurrentValues.ToObject() as T;
        return poco;
    }
    finally
    {
        context.Configuration.ProxyCreationEnabled = proxyCreationEnabled;
    }
}

Объяснение

Объект proxy вводит метод. Его тип выводится как базовый тип POCO. Теперь мы можем временно отключить ProxyCreationEnabled в контексте и скопировать прокси-объект на объект его базового типа POCO. Это действие копии с благодарностью использует несколько функций EF.

Ответ 2

При работе с EF 6 я использовал следующий код, чтобы получить базовый тип сущности POCO из типа прокси,

var entityType = ObjectContext.GetObjectType(dbEntitymodifiedEntry.Entity.GetType());

ObjectContext.GetObjectType: вернуть POCO из прокси-объекта.

ссылка: https://docs.microsoft.com/en-us/ef/ef6/fundamentals/proxies

Ответ 3

Если вам нужно сделать это из проекта, который не имеет доступа к EF или DBContext, и вы не знаете, является ли тип, на который вы ссылаетесь, прокси, вы можете сделать что-то вроде этого:

    public Type GetType
    {
        get
        {
            var thisType = _baseObject.GetType();

            if (thisType.Namespace == "System.Data.Entity.DynamicProxies")
                return thisType.BaseType;

            return thisType;
        }
    }

Ответ 4

Предлагаемый ответ имеет множество проблем - например, он не сохраняет свойства, определенные в частичных классах для сгенерированных классов POCO, и перезагружает объект из БД (что также влияет на производительность).

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

context.Configuration.ProxyCreationEnabled = false;
var changes = context.ChangeTracker.Entries().ToArray();

Ответ 5

Использовать AutoMapper 4.2.1 У него есть DynamicMap, который может удалить прокси-сервер из объекта.

     var parents = parentsRepo.GetAll().ToList();
     Mapper.CreateMap<Parent,ParentDto>();
     var parentsDto = Mapper.DynamicMap<List<ParentDto>>(parents);