2014-09-26 37 views
2

出於審計系統的目的,我需要能夠在實體保存之前通過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 
} 

這種做法的偉大工程的基本單位,但我遇到的問題是試圖找到從基底inheritied實體的導航屬性實體。例如,給定以下結構:

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

是否值得研究'entityType.DeclaredNavigationProperties'?不能看到他們是什麼或如何使用他們,所以可能對你沒有用處。 – Rhumborl 2014-09-26 15:52:16

+0

也許,我會給它一個鏡頭。編輯:不幸的是它沒有用,因爲entityType仍然是ParentEntity,Edm認爲它沒有任何聲明的導航屬性。 @Rhumborl – helloworld65 2014-09-26 16:10:26

回答

2

的問題是,你回去你感興趣的子類型的EntitySetEntitySet在基類型定義:您可以通過...

db.ParentEntities.OfType<ChildEntity>() 

因此,獲得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); 
+0

這正是我正在尋找的。謝謝! – helloworld65 2014-09-29 14:42:01