2014-04-10 35 views
8

我試圖找到一種方法,從IEdmEntity到實體框架中的CLR類型。從投射到ObjectContext獲取元數據。我使用DataSpace.OCSpace來訪問映射。我相信這是正確的,但我可能有錯誤的數據空間,DataSpaces在我的頭腦中並不清楚哪些是做什麼的,即使在這個博客http://blogs.msdn.com/b/alexj/archive/2009/04/03/tip-10-understanding-entity-framework-jargon.aspx之後。從IEdmEntity映射到CLR

最後我找回了System.Data.Entity.Core.Mapping.MappingBase對象,這些對象對我來說沒有多大幫助。從調試器看來,我可以訪問我想要的東西,但這些類標記爲內部,我無法投射給他們。

我是不是真的太難了,還是沒有辦法從實體框架中的IEdmModel回到它映射到的CLR類型?

添加代碼,試圖使它更清楚我的工作,並試圖擺脫

public Type GetIEdmEntityTypeToClrType(IEdmEntityTypeReference edmEntityType, DbContext context) 
    { 
     var metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace; 
     var fullname = edmEntityType.EntityDefinition().FullName(); 

     EntityType entityType; 
     if (metadata.TryGetItem(fullname, DataSpace.CSSpace, out entityType)) 
     { 
      //doesn't hit 
     } 
     if (metadata.TryGetItem(fullname, DataSpace.CSpace, out entityType)) 
     { 
      //hits but can't get access to CLR Type that it's mapped too. 
     } 
     if (metadata.TryGetItem(fullname, DataSpace.OCSpace, out entityType)) 
     { 
      //doesn't hit 
     } 
     if (metadata.TryGetItem(fullname, DataSpace.OSpace, out entityType)) 
     { 
      //doesn't hit 
     } 
     if (metadata.TryGetItem(fullname, DataSpace.SSpace, out entityType)) 
     { 
      //doesn't hit 
     } 

     return null; 
    } 

回答

1

我假設你正在使用實體框架6,其中映射API是不公開的。 請看看實體框架6.1 RTM的新版本:

http://blogs.msdn.com/b/adonet/archive/2014/03/17/ef6-1-0-rtm-available.aspx

更確切地說,在公共地圖API功能:

https://entityframework.codeplex.com/wikipage?title=Public%20Mapping%20API


你應該metadataWorkspace發揮獲取有關實體框架類型及其映射的信息,例如您的實體的所有簡單屬性及其CLR類型都可以像這樣獲取:

EntityObject entity = null; //your entity 
MetadataWorkspace metadataWorkspace = dataContext.MetadataWorkspace; 

Type currentEntityType = entity.GetType(); 
EntityType entityType = metadataWorkspace.GetItem<EntityType>(currentEntityType.FullName, DataSpace.OSpace); 
var simpleProperties = entityType.Properties.Where(p => p.DeclaringType == entityType && p.TypeUsage.EdmType is SimpleType); 

foreach (EdmProperty simpleProperty in simpleProperties) 
    { 
     Console.WriteLine(string.Format("Name: {0} Type: {1}", simpleProperty.Name,simpleProperty.TypeUsage)); 
    } 
+0

從我的理解是從CLR類到數據庫表列。我想要的是從IEdmEntity轉到CLR類。例如,我的IEdmEntity被稱爲CodeFirst.Customers,但我需要知道它被映射到類ProcessPro.Premier.Entities.Customers。我不需要知道數據庫表/列。 – CharlesNRice

+0

在我的代碼中,您將獲得有關實體對象屬性的CLR信息。第一行代碼中的'entityType'就是你可能需要的東西。 – Andrew

+0

http://msdn.microsoft.com/en-us/library/bb399782%28v=vs.110%29.aspx – Andrew

1

這是我有限的測試,但真的看起來像一個黑客。希望別人找到更好的東西。

public Type ConvertIEdmEntityTypeToClr(IEdmEntityType edmEntityType, DbContext context) 
    { 
     var metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace; 
     var oSpace = metadata.GetItemCollection(DataSpace.OSpace); 
     var typeName = oSpace.GetItems<EntityType>().Select(e => e.FullName).FirstOrDefault(name => 
      { 
       var fullname = name + ":" + edmEntityType.FullName(); 
       MappingBase map; 
       return metadata.TryGetItem(fullname, DataSpace.OCSpace, out map); 
      }); 

     return Type.GetType(typeName, false); 
    } 

假設OSpace Identity與CLR名稱相同。還假定OCSpace的ID是由a分隔的兩個ID。

8

你在你的問題和答案都提到的IEDM *接口不使用實體框架本身(在EF6 NuGet包沒有Microsoft.Data.Edm依賴),但與OData服務主要用於元數據(CSDL)。由於在OData CSDL中聲明的實體不一定映射到任何特定的CLR類,因此您只能間接找到它們的CLR類型。 (我認爲困惑是爲什麼安德魯的EF-only答案假設你有權訪問EntityObject。)

幸運的是,當通過OData呈現EF實體時,通常在實體的全名之間存在1:1的對應關係OData服務和EF模型的CSDL。假設情況如此,您可以像上面那樣使用edmEntityType.FullName進行搜索,但必須先從ObjectContext元數據中獲取相應的EF EntityType

DataSpace.OCSpaceMetadataWorkspace是尋找映射一個合理的地方,因爲這是在對象空間< -映射存儲>概念空間。但是當你發現,在EF6's mapping API is supposedly publicObjectTypeMapping及其相關類仍標記internal :(

然而,事實證明,你不需要做任何醜陋的反射黑客與內部OCSpace類!你可以得到映射的CLR型,直接從您的CSpace像這樣的「重災區」。

var clrTypeMetadataPropName = @"http://schemas.microsoft.com/ado/2013/11/edm/customannotation:ClrType"; 

var clrType = (Type) 
    ((IObjectContextAdapter)context).ObjectContext 
    .MetadataWorkspace 
    .GetItems<EntityType>(DataSpace.CSpace) 
    .Single(s => s.FullName == edmEntityType.FullName()) 
    .MetadataProperties 
    .Single(p => p.Name == clrTypePropName) 
    .Value; 

當然,它採用了「內部」 ClrType定製標註鍵魔術字符串,但一切都通過當前的公共API來完成我認爲這是作爲關閉,因爲直到/除非映射API的其餘部分公開爲止,您可以獲得「官方」解決方案。

4

這應該適用於實體和屬性類型。

public static Type GetClrTypeFromCSpaceType(
    this MetadataWorkspace workspace, EdmType cType) 
{ 
    var itemCollection = (ObjectItemCollection)workspace.GetItemCollection(DataSpace.OSpace); 

    if (cType is StructuralType) { 
     var osType = workspace.GetObjectSpaceType((StructuralType)cType); 
     return itemCollection.GetClrType(osType); 
    } else if (cType is EnumType) { 
     var osType = workspace.GetObjectSpaceType((EnumType)cType); 
     return itemCollection.GetClrType(osType); 
    } else if (cType is PrimitiveType) { 
     return ((PrimitiveType)cType).ClrEquivalentType; 
    } else if (cType is CollectionType) { 
     return workspace.GetClrTypeFromCSpaceType(((CollectionType)cType).TypeUsage.EdmType); 
    } else if (cType is RefType) { 
     return workspace.GetClrTypeFromCSpaceType(((RefType)cType).ElementType); 
    } else if (cType is EdmFunction) { 
     return workspace.GetClrTypeFromCSpaceType(((EdmFunction)cType).ReturnParameter.TypeUsage.EdmType); 
    } 

    return null; 
} 

使用

var entity = workspace.GetItems<EntityType>(DataSpace.CSpace).First(); 

var entityType = workspace.GetClrTypeFromCSpaceType(entity); 
var propertyType = workspace.GetClrTypeFromCSpaceType(entity.Properties[0].TypeUsage.EdmType);