出于审计系统的目的,我需要能够在保存实体之前通过ChangeTracker / ObjectStateManager检索实体的导航属性。检索到导航属性后,我将遍历每个属性并保存其名称,类型和主键。
我使用以下代码执行此操作:
var context = new SomeDbContext();
var entity = context.SomeEntities.Find(1);
entity.MakeSomeChanges();
entity.MakeMoreChanges();
context.ObjectContext.DetectChanges();
var stateManager = context.ObjectContext.ObjectStateManager;
var stateEntry = stateManager.GetObjectStateEntry(entity);
var entityType = stateEntry.EntitySet.ElementType as EntityType;
// from here I can work with the navigation properties.
foreach (var property in entityType.NavigationProperties)
{
// process nav property
}
这种方法适用于基本实体,但我遇到的问题是尝试在从基础实体继承的实体上查找导航属性。例如,给定以下结构:
public class ParentEntity
{
public int Id { get; set; }
}
public class ChildEntity : ParentEntity
{
public int NavigationEntityId { get; set; }
public virtual NavigationEntity NavigationEntity { get; set; }
}
public class NavigationEntity
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<ChildEntity> ChildEntities { get; set; }
}
我如何才能在ChildEntity上找到导航属性?如果我使用与SomeEntity相同的方法,则会发生以下情况:
var context = new SomeDbContext();
var navEntity = context.NavigationEntities.Find(1);
var childEntity = new ChildEntity();
navEntity.ChildEntities.Add(childEntity);
context.ObjectContext.DetectChanges();
var stateManager = context.ObjectContext.ObjectStateManager;
var stateEntry = stateManager.GetObjectStateEntry(childEntity);
// entityType here turns into ParentEntity, which does not have nav properties
var entityType = stateEntry.EntitySet.ElementType as EntityType;
var properties = entityType.NavigationProperties;
// properties.Count() == 0
我有什么方法可以将ParentEntity转换为ChildEntity吗? 或者,我可以采用不同的方法来检索更改跟踪器中实体的导航属性?
答案 0 :(得分:2)
问题是你回到了你感兴趣的子类型的EntitySet
。但EntitySet
是在基类型上定义的:你得到ChildEntity
s by ...
db.ParentEntities.OfType<ChildEntity>()
因此,您必须以不同的方式获取导航属性。我为此目的使用了这个小功能:
IEnumerable<NavigationProperty> GetNavigationProperies<T>(DbContext context,
T entity = default(T))
where T : class
{
var oc = ((IObjectContextAdapter)context).ObjectContext;
var entityType = oc.MetadataWorkspace
.GetItems(DataSpace.OSpace).OfType<EntityType>()
.FirstOrDefault (et => et.Name == typeof(T).Name);
return entityType != null
? entityType.NavigationProperties
: Enumerable.Empty<NavigationProperty>();
}
您可以在没有具体对象且指定了泛型类型参数的情况下调用它...
var navprops = GetNavigationProperies<ChildEntity>(db);
或使用对象并依赖于类型推断...
var navprops = GetNavigationProperies(db, childEntity);