Получить 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
где-то, потому что он использует его для ленивых свойств навигации по загрузке?
Ответы
Ответ 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.