EntityFramework 4.0 Get ComplexType Mapping - PullRequest
       6

EntityFramework 4.0 Get ComplexType Mapping

4 голосов
/ 04 ноября 2010

Я пытаюсь найти ComplexType, который сопоставлен с моим FunctionImport из моего MetadataWorkspace.

Соответствующий xml находится в CSS-пространстве edmx, но я не могу понять, как его получить.

Я могу пойти на сам EdmFunction из SSpace, но это не говорит мне о ComplexType, на который он отображается, не так ли? Я также могу перейти к самому ComplexType в CSpace, но это не говорит мне о FunctionImport, к которому он привязан ...

Связанный xml в edmx:

      <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 голосов
/ 06 ноября 2010

Согласно различным источникам, почти все пространство CSS полностью интернализировано и недоступно для разработчика. Я видел рекомендации о том, что мне следует перейти прямо к отображению 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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...