EntityFramework 4.0 获取复杂类型映射

4

我试图从我的MetadataWorkspace中找到与FunctionImport映射的ComplexType。

相关的xml在edmx的CSSpace中存在,但我无法弄清如何将其取出。

我可以从SSpace中获取EdmFunction本身,但这并不告诉我它映射到的ComplexType,对吗?我也可以在CSpace中获取ComplexType本身,但这并不告诉我它映射到的FunctionImport...

在edmx中相关的xml为:

      <FunctionImportMapping FunctionImportName="GetContactsByName" FunctionName="Test2Model.Store.GetContactsByName">
        <ResultMapping>
          <ComplexTypeMapping TypeName="Test2Model.GetContactsByName_Result">
            <ScalarProperty Name="FirstName" ColumnName="FirstName" />
            <ScalarProperty Name="LastName" ColumnName="LastName" />
            <ScalarProperty Name="Address1" ColumnName="Address1" />
            <ScalarProperty Name="Address2" ColumnName="Address2" />
            <ScalarProperty Name="City" ColumnName="City" />
            <ScalarProperty Name="StateID" ColumnName="StateID" />
            <ScalarProperty Name="Country" ColumnName="Country" />
          </ComplexTypeMapping>
        </ResultMapping>
      </FunctionImportMapping>

运行时,我可以获取StorageEntityMappingCollection,但我不确定接下来该怎么做:

((System.Data.Mapping.StorageMappingItemCollection)  
metadataWorkspace.GetItemCollection(DataSpace.CSSpace)).First() // then what....all I see after this is a bunch of MetadataProperties which seem to take me in circles...
1个回答

3
根据各种来源的说法,CSSpace几乎完全内部化且无法访问。我看到建议直接使用映射xml,但我真的不想这样做...因此,我最终想出了这个解决方案,似乎很适合从ObjectContext中获取所有映射。
注意...这很耗费资源...所以如果其他人发现这有用并采用此方法,他们应该确保对其进行缓存。
internal class Resource
{
     public string Name {get; set; }
     public Type Type { get; set; }
     public IEnumerable<ResourceParameter> Parameters { get; private set; }
}

internal class ResourceParameter
{
     public string Name { get; set; }
     public Type Type { get; set; }
}

internal class EntityFrameworkExtensions 
{
    public static IEnumerable<Resource> GetResources(this ObjectContext objectContext, IEnumerable<Assembly> assemblies)
    {
        MetadataWorkspace metadataWorkspace = objectContext.MetadataWorkspace;

        foreach (Assembly assembly in assemblies)
        {
            metadataWorkspace.LoadFromAssembly(assembly);
        }

        ReadOnlyCollection<EntityType> cSpaceEntityTypes = metadataWorkspace.GetItems<EntityType>(DataSpace.CSpace);
        if (cSpaceEntityTypes != null)
        {
            foreach (Type type in cSpaceEntityTypes.Select(t => metadataWorkspace.GetClrType(t, assemblies)))
            {
                yield return new Resource { Type = type, Name = type.Name };
            }
        }

        IEnumerable<EdmFunction> cSpaceFunctions = metadataWorkspace.GetItems<EntityContainer>(DataSpace.CSpace).SelectMany(c => c.FunctionImports));
        if (cSpaceFunctions != null)
        {
            foreach (EdmFunction function in cSpaceFunctions)
            {
                Type returnType = metadataWorkspace.GetClrType(function.ReturnParameter.TypeUsage.EdmType, assemblies);
                IEnumerable<ResourceParameter> parameters = function.Parameters.Select(p => new ResourceParameter(metadataWorkspace.GetClrType(p.TypeUsage.EdmType, assemblies), p.Name));
                yield return new Resource { Type = returnType, Name = function.Name, Parameters = parameters };
            }
        }
    }

    public static string GetClrTypeName(this MetadataWorkspace metadataWorkspace, StructuralType cSpaceType)
    {
        if (cSpaceType != null)
        {
            StructuralType oSpaceType;

            if (metadataWorkspace.TryGetObjectSpaceType(cSpaceType, out oSpaceType))
            {
                // interesting note: oSpaceType is of type ClrType - an internal EF type that contains a EdmType to CLR type mapping...  
                // so instead of getting the type name, we could go straight for the type  
                // by doing: oSpaceType.GetProperty("ClrType",BindingFlags.Instance|BindingFlags.NonPublic).GetValue(oSpaceType, null);  
                // but the classes are internal, so they might change and I don't want to touch them directly...
                return oSpaceType.FullName;
            }
        }

        return null;
    }

    public static Type GetClrType(this MetadataWorkspace metadataWorkspace, EdmType cSpaceEdmType, IEnumerable<Assembly> assemblies)
    {
        var collectionType = cSpaceEdmType as CollectionType;
        if (collectionType != null)
        {
            Type elementType = metadataWorkspace.GetClrType(collectionType.TypeUsage.EdmType, assemblies);

            return elementType;
        }

        var structuralType = cSpaceEdmType as StructuralType;
        if (structuralType != null)
        {
            var name =  metadataWorkspace.GetClrTypeName(structuralType);
            foreach(var asm in assemblies) 
            {
                 var clrType = asm.GetType(name);
                 if (clrType != null) 
                 {
                       return clrType;
                 }
            }
        }

        var primitiveType = cSpaceEdmType as PrimitiveType;
        if (primitiveType != null)
        {
            return primitiveType.ClrEquivalentType;
        }

        return null;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接