2010-11-04 83 views
4

我試圖從我的MetadataWorkspace中找到映射到我的FunctionImport的ComplexType。EntityFramework 4.0獲取複雜類型映射

相關的XML在EDMX的CSS空間中,但我無法弄清楚如何搞定它。

我能去的EdmFunction本身從SSpace,但並沒有告訴我的ComplexType,它的映射,是嗎?我也可以去爲自己的ComplexType在CSpace,但並沒有告訴我它映射到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... 

回答

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; 
    } 
}