从IEdmEntity映射到CLR

Cha*_*ice 8 .net c# entity-framework

我试图找到一种方法从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;
    }
Run Code Online (Sandbox Code Playgroud)

rob*_*b3c 8

您在问题和答案中提到的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像上面那样使用搜索,但是您必须首先EntityTypeObjectContext元数据中获取相应的EF .

DataSpace.OCSpacein MetadataWorkspace是寻找映射的合理位置,因为那是存储Object Space < - > Conceptual Space映射的地方.但正如您所发现的,虽然EF6的映射API应该是公开的,但ObjectTypeMapping其相关类仍然标记为internal:(

然而,事实证明你不需要对内部OCSpace类做任何丑陋的反思黑客攻击!您可以直接从'hit'获取映射的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 == clrTypeMetadataPropName )
    .Value;
Run Code Online (Sandbox Code Playgroud)

当然,它使用'内部'ClrType自定义注释键魔术字符串,但一切都是通过当前的公共API完成的.我认为,除非映射API的其余部分公开,否则您可以获得"正式"解决方案.


And*_*rew 1

我假设您使用的是实体框架 6,其中映射 API 不公开。请查看新版本的 Entity Framework 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));
     }
Run Code Online (Sandbox Code Playgroud)