从实体框架中的实体获取DbContext

Dir*_*oer 26 c# entity-framework

在Visual Studio中的调试会话中,我深入到Business层中的某个位置,试图找出实体在尝试持久化更改时表现异常的原因.

在调用堆栈中此处获取对此实体所属的DbContext的引用确实很有帮助.

即,看看这个实体的状态是什么(Unchanged,Modified等).

所以我正在寻找这样的辅助方法:

var db_context = DbContextHelpers.GetDbContext(entity);

// after that I could do something like this
var state = db_context.Entry(entity);
Run Code Online (Sandbox Code Playgroud)

我可以在调试期间在立即窗口中使用这些东西.

任何建议?

额外的笔记

实体必须知道DbContext某个地方,因为它正在使用它来延迟加载导航属性?

Dir*_*oer 25

public static DbContext GetDbContextFromEntity(object entity)
{
    var object_context = GetObjectContextFromEntity( entity );

    if ( object_context == null )
        return null;

    return new DbContext( object_context, dbContextOwnsObjectContext: false );
}

private static ObjectContext GetObjectContextFromEntity(object entity)
{
    var field = entity.GetType().GetField("_entityWrapper");

    if ( field == null )
        return null;

    var wrapper  = field.GetValue(entity);
    var property = wrapper.GetType().GetProperty("Context");
    var context  = (ObjectContext)property.GetValue(wrapper, null);

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

  • 我用过这个,它在大多数情况下都有效。在一个项目中,entity.GetType().GetField("_entityWrapper") 返回 null,您知道可能的原因吗? (2认同)
  • @gillesemmanuel如果没有创建代理类,例如,如果您禁用了代理创建http://stackoverflow.com/questions/24674310/disable-dynamic-proxy-in-entity-framework-globally或者如果您的实体类,则会发生这种情况不符合代理类的要求 https://msdn.microsoft.com/en-us/library/dd468057(v=vs.100).aspx 等。 (2认同)

ker*_*elk 14

对于EF6,我稍微修改了Dirk的答案:

    public static DbContext GetDbContextFromEntity(object entity)
    {
        var object_context = GetObjectContextFromEntity(entity);

        if (object_context == null || object_context.TransactionHandler == null)
            return null;

        return  object_context.TransactionHandler.DbContext;
    }

    private static ObjectContext GetObjectContextFromEntity(object entity)
    {
        var field = entity.GetType().GetField("_entityWrapper");

        if (field == null)
            return null;

        var wrapper = field.GetValue(entity);
        var property = wrapper.GetType().GetProperty("Context");
        var context = (ObjectContext)property.GetValue(wrapper, null);

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

没有新的DbContext(),它可以转换为您的主要Entities类.

注意:对于上述null返回值的问题,如果实体尚未保存/提交,则会发生这种情况.只能在.Local中找到的新实体似乎没有"_entityWrapper"字段.


Axi*_*ili 5

我找到了另一种获取ObjectContext的方法.不知道它是否更好.

public static ObjectContext GetContext(this IEntityWithRelationships entity)
{
  if (entity == null)
    throw new ArgumentNullException("entity");

  var relationshipManager = entity.RelationshipManager;
  var relatedEnd = relationshipManager.GetAllRelatedEnds().FirstOrDefault();

  if (relatedEnd == null)
    throw new Exception("No relationships found");

  var query = relatedEnd.CreateSourceQuery() as ObjectQuery;
  if (query == null)
    throw new Exception("The Entity is Detached");

  return query.Context;
}
Run Code Online (Sandbox Code Playgroud)

你可以使用它:

MyContext context = myEntity.GetContext() as MyContext;
Run Code Online (Sandbox Code Playgroud)