[英]Mapping from IEdmEntity to CLR
我試圖找到一種方法從IEdmEntity到實體框架中的CLR類型。 從轉換到ObjectContext來獲取元數據。 我正在使用DataSpace.OCSpace來訪問映射。 我相信這是正確的,但我可能有錯誤的DataSpace,即使在這個博客http://blogs.msdn.com/b/alexj/archive/2009/04/之后,DataSpaces也不清楚我的腦袋里做了什么。 03 / tip-10-understanding-entity-framework-jargon.aspx 。
最后我得到了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;
}
你在問題和答案中提到的* IEdm **接口本身不被Entity Framework使用(EF6 NuGet包沒有Microsoft.Data.Edm依賴),但主要用於OData服務元數據(CSDL)。 由於在OData CSDL中聲明的實體不一定映射到任何特定的CLR類,因此您只能間接找到它們的CLR類型。 (我認為混淆是為什么安德魯的EF專用答案假設你有權訪問EntityObject
。)
幸運的是,當通過OData呈現EF實體時,OData服務和EF模型的CSDL中的實體的全名之間通常存在1:1的對應關系。 假設是這種情況,您可以像上面那樣使用edmEntityType.FullName
進行搜索,但您必須首先從ObjectContext
元數據中獲取相應的EF EntityType
。
MetadataWorkspace
中的DataSpace.OCSpace
是查找映射的合理位置,因為這是存儲對象空間< - >概念空間映射的位置。 但正如您所發現的,雖然EF6的映射API應該是公開的 ,但ObjectTypeMapping
及其相關類仍然標記為internal
:(
然而,事實證明,您不需要使用內部OCSpace
類進行任何丑陋的反射黑客攻擊! 你可以直接從CSpace
'hit'獲取映射的CLR類型,如下所示:
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 == clrTypeMetadataPropName )
.Value;
當然,它使用'內部'ClrType自定義注釋鍵魔術字符串,但一切都是通過當前的公共API完成的。 我認為,除非映射API的其余部分公開,否則您可以獲得“正式”解決方案。
這應該適用於實體和屬性類型。
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);
我假設您正在使用Entity Framework 6,其中Mapping API不公開。 請查看Entity Framework 6.1 RTM的新版本:
http://blogs.msdn.com/b/adonet/archive/2014/03/17/ef6-1-0-rtm-available.aspx
更具體地說,在Public Mapping 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));
}
這是我的有限測試,但真的看起來像一個黑客。 希望別人找到更好的東西。
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標識與CLR名稱相同。 還假設OCSpace的ID是兩個放在一起的ID,分隔為:。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.