結構化型別 (中繼資料)
在 實體資料模型 (EDM) 中,結構化型別是具有成員的 EDM 型別。成員會定義衍生自 StructuralType 類別之型別的內容。StructuralType 類別有幾個衍生型別,例如 EntityType、RelationshipType 和 ComplexType。
EntityType 代表最上層概念,例如 EDM 中的客戶或訂單。RelationshipType 是代表 EDM 中關聯之 AssociationType 的基底類型。如需 EDM 中實體和關聯的詳細資訊,請參閱實體類型 (EDM) 和關聯 (EDM)。
ComplexType 代表包含類似實體類型的屬性集、但不包含索引鍵屬性的型別。如需 EDM 中複雜類型的詳細資訊,請參閱複雜類型 (EDM)。
在 EDM 結構描述中,EntityType、RelationshipType 和 ComplexType 都有子元素或成員。例如,實體類型的屬性是它的成員;同樣地,關聯性的兩端也是它的成員。每一個成員都有一個宣告型別,而且可能具有 Nullability 限制式或是預設值的指派。
下列各節將提供有關成員的詳細資訊。
成員
在 EDM 中,成員會定義衍生自 StructuralType 類別之型別的內容。例如,下列 XML 表示是來自於 AdventureWorks 完整概念結構描述 (EDM) 主題提供的 AdventureWorks 概念結構描述 (.csdl) 檔案。這個 XML 表示會定義 EntityType Department。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>
您可以使用 StructuralType 提供的 System.Data.Metadata.Edm.StructuralType.Members 屬性,取得任何結構化型別上的成員清單。Members 屬性會傳回保存 EdmMember 物件的 ReadOnlyMetadataCollection。
衍生自 StructuralType 的型別會將其成員儲存在繼承自 StructuralType 的 Members 屬性中。
除了繼承自 StructuralType 的 Members 屬性之外,每一個衍生型別也會提供某些其他屬性,以取得可於該型別上宣告的特殊成員清單。例如,System.Data.Metadata.Edm.EntityType.Properties 會傳回保存 EdmProperty 物件的集合。
同樣地,RelationshipType 包含了可傳回 RelationshipEndMember 物件集合的 System.Data.Metadata.Edm.RelationshipType.RelationshipEndMembers 屬性。請注意,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) 和 HOW TO:定義具有複雜類型的模型 (Entity Framework)。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