结构化类型(元数据)
在 实体数据模型 (EDM) 中,结构化类型是具有成员的 EDM 类型。成员定义从 StructuralType 类派生的类型的内容。StructuralType 类具有多个派生类,如 EntityType、RelationshipType 和 ComplexType。
EntityType 表示顶级概念,如 EDM 中的客户或订单。RelationshipType 是在 EDM 中表示关联的 AssociationType 的基类型。有关 EDM 中的实体和关联的更多信息,请参见实体类型 (EDM) 和关联 (EDM)。
ComplexType 表示的类型包括一组类似于实体类型的属性,但不包括键属性。有关 EDM 中的复杂类型的更多信息,请参见复杂类型 (EDM)。
在 EDM 架构中,EntityType、RelationshipType 和 ComplexType 具有子元素或成员。例如,某个实体类型的属性是其成员;同样,某个关系的端也是其成员。每个成员都有一个声明类型,可能具有空值约束或默认值指定。
以下各节提供有关成员的详细信息。
成员
在 EDM 中,成员定义从 StructuralType 类派生的类型的内容。例如,以下 XML 表示形式来自在 AdventureWorks 完整概念架构 (EDM) 主题中给出的 AdventureWorks 概念性架构 (.csdl) 文件。此 XML 表示形式定义系 EntityType。Department(系)实体的成员为 DepartmentID、Name、GroupName、ModifiedDate 和 EmployeeDepartmentHistory。
<EntityType Name="Department">
<Key>
<PropertyRef Name="DepartmentID" />
</Key>
<Property Name="DepartmentID" Type="Int16" Nullable="false" />
<Property Name="Name" Type="String" Nullable="false" />
<Property Name="GroupName" Type="String" Nullable="false" />
<Property Name="ModifiedDate" Type="DateTime" Nullable="false" />
<NavigationProperty Name="EmployeeDepartmentHistory" Relationship="Adventureworks.FK_EmployeeDepartmentHistory_Department_DepartmentID" FromRole="Department" ToRole="EmployeeDepartmentHistory" />
</EntityType>
可以使用 System.Data.Metadata.Edm.StructuralType.Members 属性(由 StructuralType 提供)获得任何结构化类型的成员列表。Members 属性返回 ReadOnlyMetadataCollection,其中持有 EdmMember 对象。
从 StructuralType 派生的类型将其成员存储在从 StructuralType 继承的 Members 属性中。
除了从 StructuralType 继承的 Members 属性之外,每个派生类型都提供了一些附加属性,以获得可针对该类型声明的特殊成员的列表。例如,System.Data.Metadata.Edm.EntityType.Properties 返回一个持有 EdmProperty 对象的集合。
同样,RelationshipType 包含 System.Data.Metadata.Edm.RelationshipType.RelationshipEndMembers 属性,该属性返回 RelationshipEndMember 对象的集合。请注意,EdmProperty 和 RelationshipEndMember 同时派生自 EdmMember。
以下列表提供了一组属性,您可以使用它们来检索结构化类型的成员:
System.Data.Metadata.Edm.EntityType.Members:获取 EntityType 对象的所有成员的列表。EntityType 的成员可以包含 EntityType 对象的属性、导航属性和键成员。System.Data.Metadata.Edm.EntityType.Members 属性继承自 StructuralType 类。有关如何在概念性架构中指定 EntityType 的成员的更多信息,请参见 EntityType 元素 (CSDL)。
System.Data.Metadata.Edm.EntityType.Properties:获取 EntityType 对象的属性的列表。有关如何在概念性架构中指定 EntityType 的属性的更多信息,请参见实体类型 (EDM) 和 EntityType 元素 (CSDL)。
System.Data.Metadata.Edm.EntityType.NavigationProperties:获取 EntityType 对象的导航属性的列表。有关如何在概念性架构中指定 EntityType 的导航属性的更多信息,请参见实体类型 (EDM) 和 EntityType 元素 (CSDL)。
System.Data.Metadata.Edm.EntityType.KeyMembers:获取 EntityType 对象的键成员的列表。此属性继承自 EntityTypeBase 类。
System.Data.Metadata.Edm.RelationshipType.RelationshipEndMembers:获取 RelationshipType 对象的 End 成员的列表。
System.Data.Metadata.Edm.AssociationType.AssociationEndMembers:获取 AssociationType 对象的 End 成员的列表。有关如何在概念性架构中指定 AssociationType 的 End 成员的更多信息,请参见Association 元素 (CSDL)。
System.Data.Metadata.Edm.ComplexType.Properties:获取 ComplexType 对象的属性的列表。有关如何在概念性架构中指定 ComplexType 的属性的更多信息,请参见复杂类型 (EDM)和如何:使用复杂类型定义模型(实体框架)。ComplexType 类中的代码示例演示如何在指定模型中检索复杂类型的属性。
下面的代码示例通过连接获取元数据工作区,然后使用该元数据工作区在指定的模型中检索有关实体和关系类型的成员的信息。请注意,元数据工作区是一个为检索元数据提供支持的运行时服务组件。
该代码示例使用 CSpace 指定模型。CSpace 表示概念性模型的默认名称。此代码示例使用 AdventureWorks 完整模型 (EDM) 主题中提供的 AdventureWorks 模型。有关应用程序配置文件的示例,请参见使用 AdventureWorks 对象模型 (EDM)。
using System;
using System.Data;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Data.EntityClient;
using System.Data.Metadata.Edm;
class GetMembersExample
{
static void Main()
{
try
{
// Establish a connection to the underlying data provider by
// using the connection string specified in the config file.
using (EntityConnection connection =
new EntityConnection("Name=AdventureWorksEntities"))
{
// Open the connection.
connection.Open();
// Access the metadata workspace.
MetadataWorkspace workspace =
connection.GetMetadataWorkspace();
// Get members of entity types and relationship types.
GetMembers(workspace, DataSpace.CSpace);
}
}
catch (MetadataException exceptionMetadata)
{
Console.WriteLine("MetadataException: {0}",
exceptionMetadata.Message);
}
catch (System.Data.MappingException exceptionMapping)
{
Console.WriteLine("MappingException: {0}",
exceptionMapping.Message);
}
}
public static void GetMembers(
MetadataWorkspace workspace, DataSpace model)
{
// Get a collection of entity types.
ReadOnlyCollection<EntityType> entityTypes =
workspace.GetItems<EntityType>(model);
// Iterate through the collection to get each entity type.
foreach (EntityType entityType in entityTypes)
{
Console.WriteLine(
"\n\n***EntityType Name: {0}, Namespace: {1}, RefType: {2}",
entityType.Name,
entityType.NamespaceName,
entityType.GetReferenceType());
Console.WriteLine(
"\nGet all members of the current EntityType object ==>");
// Iterate through the collection to get all members of the
// current EntityType object.
foreach (EdmMember member in entityType.Members)
{
Console.Write(" Member Name: {0} ", member.Name);
}
Console.WriteLine(
"\nGet only the properties of the current "+
"EntityType object ==>");
// Iterate through the collection to get each property of the
// current EntityType object.
foreach (EdmProperty property in entityType.Properties)
{
Console.Write(" Property Name: {0} ", property.Name);
Console.WriteLine(
" Property declaring Type: {0}, edmtype: {1}," +
" default: {2}, nullable: {3} ",
property.DeclaringType, property.TypeUsage.EdmType,
property.Default, property.Nullable);
}
Console.WriteLine("\nGet only the navigation properties of " +
"the current EntityType object ==>");
// Iterate through the collection to get each navigation
// property of the current EntityType object.
foreach (NavigationProperty property in
entityType.NavigationProperties)
{
Console.Write(
"Name: {0}, RelationshipTypeName: {1}, " +
"ToEndMemberName: {2} ",
property.Name, property.RelationshipType.Name,
property.ToEndMember.Name);
}
Console.WriteLine("\nGet only the key members of the " +
"current EntityType object ==>");
// Iterate through the collection to get each key members of
// the current EntityType object.
ReadOnlyMetadataCollection<EdmMember> collectionKeyMembers =
entityType.KeyMembers;
if (collectionKeyMembers.Count != 0)
{
Console.Write(" Key: {0} ",
GetKeys(collectionKeyMembers));
}
}
// Get a collection of relationship types.
ReadOnlyCollection<RelationshipType> relationshipTypes =
workspace.GetItems<RelationshipType>(model);
// Iterate through the collection to get each relationship type.
foreach (RelationshipType relationType in relationshipTypes)
{
Console.WriteLine(
"\n\nRelationshipType Name: {0}, Namespace: {1}",
relationType.Name,
relationType.NamespaceName);
Console.WriteLine(
"\nGet all members of the current "+
"RelationshipType object ==>");
// Iterate through the collection to get all members of the
// current RelationshipType object.
foreach (EdmMember member in relationType.Members)
{
Console.Write(" Member Name: {0} ", member.Name);
}
Console.WriteLine(
"\nGet only the end members of the current " +
"RelationshipType object ==>");
// Iterate through the collection to get only the end
// members of
// the current RelationshipType object.
foreach (RelationshipEndMember endMember in
relationType.RelationshipEndMembers)
{
Console.Write(" End Member Name: {0} ", endMember.Name);
}
}
}
// Returns the keys in a string format.
private static string GetKeys(ICollection<EdmMember> keyMembers)
{
StringBuilder result = new StringBuilder();
foreach (EdmMember member in keyMembers)
{
if (result.Length != 0)
{
result.Append(" ");
}
result.Append(member.Name);
}
return result.ToString();
}
}
Imports System
Imports System.Data
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Text
Imports System.Data.EntityClient
Imports System.Data.Metadata.Edm
Class GetMembersExample
Public Shared Sub Main()
Try
' Establish a connection to the underlying data provider by
' using the connection string specified in the config file.
Using connection As EntityConnection = _
New EntityConnection("Name=AdventureWorksEntities")
' Open the conection.
connection.Open()
' Access the metadata workspace.
Dim workspace As MetadataWorkspace = _
connection.GetMetadataWorkspace
' Get members of entity types and relationship types.
GetMembers(workspace, DataSpace.CSpace)
End Using
Catch exceptionMetadata As MetadataException
Console.WriteLine("MetadataException: {0}", _
exceptionMetadata.Message)
Catch exceptionMapping As MappingException
Console.WriteLine("MappingException: {0}", _
exceptionMapping.Message)
End Try
End Sub
Public Shared Sub GetMembers(ByVal workspace As MetadataWorkspace, _
ByVal model As DataSpace)
' Get a collection of entity types.
Dim entityTypes As ReadOnlyCollection(Of EntityType) = _
workspace.GetItems(Of EntityType)(model)
' Iterate through the collection to get each entity type.
Dim entityType As EntityType
For Each entityType In entityTypes
Console.WriteLine( _
ControlChars.Lf & ControlChars.Lf & _
"***EntityType Name: {0}, Namespace: {1}, RefType: {2}", _
entityType.Name, entityType.NamespaceName, _
entityType.GetReferenceType)
Console.WriteLine(ControlChars.Lf & _
"Get all members of the current EntityType object ==>")
' Iterate through the collection to get all members of the
' current EntityType object.
Dim member As EdmMember
For Each member In entityType.Members
Console.Write(" Member Name: {0} ", member.Name)
Next
Console.WriteLine(ControlChars.Lf & _
"Get only the properties of the current EntityType object ==>")
' Iterate through the collection to get each property of the
' current EntityType object.
Dim property1 As EdmProperty
For Each property1 In entityType.Properties
Console.Write(" Property Name: {0} ", property1.Name)
Console.WriteLine( _
" Property declaring Type: {0}, edmtype: {1}, default: {2}, nullable: {3} ", _
New Object() {property1.DeclaringType, _
property1.TypeUsage.EdmType, _
property1.Default, property1.Nullable})
Next
Console.WriteLine(ControlChars.Lf & _
"Get only the navigation properties of the current EntityType object ==>")
' Iterate through the collection to get each navigation
' property of the current EntityType object.
Dim property2 As NavigationProperty
For Each property2 In entityType.NavigationProperties
Console.Write( _
"Name: {0}, RelationshipTypeName: {1}, ToEndMemberName: {2} ", _
property2.Name, property2.RelationshipType.Name, _
property2.ToEndMember.Name)
Next
Console.WriteLine(ControlChars.Lf & _
"Get only the key members of the current EntityType object ==>")
' Iterate through the collection to get each key members of
' the current EntityType object.
Dim collectionKeyMembers As _
ReadOnlyMetadataCollection(Of EdmMember) = _
entityType.KeyMembers
If (collectionKeyMembers.Count <> 0) Then
Console.Write(" Key: {0} ", GetKeys(collectionKeyMembers))
End If
Next
' Get a collection of relationship types.
Dim relationshipTypes As _
ReadOnlyCollection(Of RelationshipType) = _
workspace.GetItems(Of RelationshipType)(model)
' Iterate through the collection to get each relationship type.
Dim relationType As RelationshipType
For Each relationType In relationshipTypes
Console.WriteLine(ControlChars.Lf & ControlChars.Lf & _
"RelationshipType Name: {0}, Namespace: {1}", _
relationType.Name, relationType.NamespaceName)
Console.WriteLine(ControlChars.Lf & _
"Get all members of the current RelationshipType object ==>")
' Iterate through the collection to get all members of the
' current RelationshipType object.
Dim member As EdmMember
For Each member In relationType.Members
Console.Write(" Member Name: {0} ", member.Name)
Next
Console.WriteLine(ControlChars.Lf & _
"Get only the end members of the current RelationshipType object ==>")
Dim endMember As RelationshipEndMember
' Iterate through the collection to get only the
' end members of
' the current RelationshipType object.
For Each endMember In relationType.RelationshipEndMembers
Console.Write(" End Member Name: {0} ", endMember.Name)
Next
Next
End Sub
Public Shared Function GetKeys(ByVal keyMembers As _
ICollection(Of EdmMember)) As String
Dim result As New StringBuilder
Dim member As EdmMember
For Each member In keyMembers
If (result.Length <> 0) Then
result.Append(" ")
End If
result.Append(member.Name)
Next
Return result.ToString
End Function
End Class