Get underlying entity object from entity framework proxy

前端 未结 6 1752
逝去的感伤
逝去的感伤 2020-12-04 16:41

I have an entity by getting it from DbEntityEntry.Entity. This returns the Entity Framework proxy for the entity.

How do I access the underlying object

相关标签:
6条回答
  • 2020-12-04 17:09

    To get a JSON friendly object in EF Core I used this method:

    T UnProxy<T>(T efObject) where T : new()
    {
        var type = efObject.GetType();
    
        if (type.Namespace == "Castle.Proxies")
        {
            var baseType = type.BaseType;
            var returnObject = new T();
            foreach (var property in baseType.GetProperties())
            {
                var propertyType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
                if (propertyType.Namespace == "System")
                {
                    var value = property.GetValue(efObject);
                    property.SetValue(returnObject, value);
                }
            }
            return returnObject;
        }
    
        return efObject;
    }
    
    0 讨论(0)
  • 2020-12-04 17:13

    While working with EF 6 i used the following code to get the underlying POCO entity type from proxy type,

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

    ObjectContext.GetObjectType : Return the POCO from proxy object

    reference : https://docs.microsoft.com/en-us/ef/ef6/fundamentals/proxies

    0 讨论(0)
  • 2020-12-04 17:27

    If you end up needing to do this from a project that does not have access to EF or the DBContext, and you don't know if the type you are referencing is a proxy you can do something like this:

        public Type GetType
        {
            get
            {
                var thisType = _baseObject.GetType();
    
                if (thisType.Namespace == "System.Data.Entity.DynamicProxies")
                    return thisType.BaseType;
    
                return thisType;
            }
        }
    
    0 讨论(0)
  • 2020-12-04 17:28

    First I should say there is no underlying object. A proxy doesn't wrap an entity object (decorator pattern), it derives from it (inheritance). So we can't unwrap the entity, we can only convert a proxy to a base object. Conversion (contrary to casting) always creates a new object.

    For this conversion, we can exploit the fact that most of the time, by the way proxies are returned by EF, the compile time type of a proxy is the base type. That is, if a proxy is entered as an argument to a generic method, the generic parameter will be inferred as the base type. This feature allows us to create a method that does what you want:

    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;
        }
    }
    

    Explanation

    The proxy object enters the method. Its type is inferred as the base POCO type. Now we can temporarily turn off ProxyCreationEnabled on the context and copy the proxy object to an object of its base POCO type. This copy action gratefully uses a few EF features.

    0 讨论(0)
  • 2020-12-04 17:30

    Use AutoMapper 4.2.1 It is having DynamicMap which can remove the Proxy from the object.

         var parents = parentsRepo.GetAll().ToList();
         Mapper.CreateMap<Parent,ParentDto>();
         var parentsDto = Mapper.DynamicMap<List<ParentDto>>(parents);
    
    0 讨论(0)
  • 2020-12-04 17:31

    Proposed answer has number of problems - for example it doesn't preserve properties defined in partial classes for generated POCO classes and it reloads entity from DB (which also hits the performance).

    You can try to turn proxies off before you ask for changes, but it may not help if entities have already been loaded before - they'll be proxy types already (probably it depends on EF version, but it worked out once and didn't work another time in my experience). You also need to materialize it before you turn proxies back - it isn't obvious but it's just deferred query which has to be materialized:

    context.Configuration.ProxyCreationEnabled = false;
    var changes = context.ChangeTracker.Entries().ToArray();
    
    0 讨论(0)
提交回复
热议问题