gpt4 book ai didi

.net - EntityFramework 4.0 获取复杂类型映射

转载 作者:行者123 更新时间:2023-12-02 08:58:40 25 4
gpt4 key购买 nike

我正在尝试从 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...

最佳答案

根据各种消息来源,几乎所有的 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;
}
}

关于.net - EntityFramework 4.0 获取复杂类型映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4100663/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com