簡體   English   中英

從IEdmEntity映射到CLR

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM