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

Получить DbContext из Entity в Entity Framework

Я глубоко где-то в бизнес-слое в сеансе отладки в Visual Studio, пытаясь понять, почему Entity ведет себя странно, пытаясь сохранить изменения.

Было бы полезно получить ссылку на DbContext, к которой принадлежит это Сущность, в этот момент в стеке вызовов.

т.е. для просмотра состояния этого объекта (без изменений, модификации и т.д.).

Итак, я ищу вспомогательный метод, подобный этому:

var db_context = DbContextHelpers.GetDbContext(entity);

// after that I could do something like this
var state = db_context.Entry(entity);

Я могу использовать этот материал в окне Immediate во время отладки.

Есть ли какие-либо предложения?

Дополнительные заметки

Объект должен знать о DbContext где-то, потому что он использует его для ленивых свойств навигации по загрузке?

4b9b3361

Ответ 1

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

Ответ 2

Я нашел другой способ, чтобы получить 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;
}

И вы можете использовать его как:

MyContext context = myEntity.GetContext() as MyContext;

Ответ 3

Для 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;
    }

Нет нового DbContext(), и он вставляется в ваш основной класс Entities.

Примечание. К вышеуказанному вопросу о возвращаемом значении null это произойдет, если объект не был сохранен/зафиксирован. Новые объекты, которые могут быть найдены только в .Local, похоже, не имеют поля _entityWrapper.