从实体框架代理获取底层实体对象

Ric*_*ich 38 c# entity-framework

从一个实体获得它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
Run Code Online (Sandbox Code Playgroud)

小智 42

在使用EF 6时,我使用以下代码从代理类型中获取基础POCO实体类型,

var entityType = ObjectContext.GetObjectType(dbEntitymodifiedEntry.Entity.GetType());
Run Code Online (Sandbox Code Playgroud)

ObjectContext.GetObjectType :从代理对象返回POCO

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

  • 对像我这样眼睛不好的人的说明.. 这是一个大写的 O ObjectContext 意味着它是一个静态方法 =) http://stackoverflow.com/a/16005340/3507333 (2认同)

Ger*_*old 36

首先,我应该说没有潜在的对象.代理不包装实体对象(装饰器模式),它是从它派生的(继承).所以我们无法解开实体,我们只能代理转换为基础对象.转换(与转换相反)始终会创建一个新对象.

对于这种转换,我们可以利用这样的事实:在大多数情况下,通过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;
    }
}
Run Code Online (Sandbox Code Playgroud)

说明

代理对象进入方法.其类型被推断为基础POCO类型.现在我们可以暂时关闭ProxyCreationEnabled上下文并将代理对象复制到其基本POCO类型的对象.此复制操作非常感谢使用一些EF功能.

  • 如果在其他线程中使用了上下文,这可能会让你失望......只是一个警告. (5认同)
  • 无论如何,使用多线程中的上下文的@IDisposable是不健康的.是的,它必须是一个被跟踪的实体. (2认同)

Ant*_*ols 19

如果您最终需要从无法访问EF或DBContext的项目执行此操作,并且您不知道您引用的类型是否是代理,则可以执行以下操作:

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

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

            return thisType;
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • @codetuner如果您的项目中没有对Entity Framework的引用,那么您根本无法访问DbContext. (3认同)
  • @codetuner另外,我的API需要传递一个`object`类型的变量.所以我不能在不事先知道类型的情况下使用`.Entity()`方法,这违背了我需要解决方案的目的. (3认同)