Structural Types (Metadata)

In the Entity Data Model (EDM), structural types are EDM types that have members. Members define the content of the types derived from the StructuralType class. The StructuralType class has several derived types, such as the EntityType, the RelationshipType, and the ComplexType.

The EntityType represents a top-level concept, such as a customer or an order in the EDM. The RelationshipType is a base type for the AssociationType that represents an association in the EDM. For more information about the entities and associations in the EDM, see Entity Type (EDM) and Association (EDM).

The ComplexType represents a type that includes a set of properties like an entity type but does not include a key property. For more information about the complex types in the EDM, see Complex Type (EDM).

In the EDM schemas, the EntityType, the RelationshipType and the ComplexType have sub-elements or members. For example, the properties of an entity type are its members; similarly, the ends of a relationship are its members, too. Each member has a declaring type and may have the Nullability constraint or a Default value assignment.

The following sections provide detailed information about members.

Members

In the EDM, members define the content of the types derived from the StructuralType class. For example, the following XML representation is from the AdventureWorks conceptual schema (.csdl) file given in the AdventureWorks Complete Conceptual Schema (EDM) topic. This XML representation defines the Department EntityType. The members of the Department entity are DepartmentID, Name, GroupName, ModifiedDate, and 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>

You can get a list of members on any structural type by using the System.Data.Metadata.Edm.StructuralType.Members property provided by the StructuralType. The Members property returns a ReadOnlyMetadataCollection that holds the EdmMember objects.

The types that derive from the StructuralType store their members in the Members property inherited from the StructuralType.

In addition to the Members property inherited from the StructuralType, each derived type provides some additional properties to get the list of special members that can be declared on that type. For example, System.Data.Metadata.Edm.EntityType.Properties returns a collection that holds the EdmProperty objects.

Similarly, RelationshipType contains System.Data.Metadata.Edm.RelationshipType.RelationshipEndMembers property that returns a collection of RelationshipEndMember objects. Note that both the EdmProperty and the RelationshipEndMember are derived from the EdmMember.

The following list provides a set of properties that you can use to retrieve the members of the structural types:

  • System.Data.Metadata.Edm.EntityType.Members: Gets a list of all members of the EntityType object. The members of the EntityType can include properties, navigation properties, and key members of the EntityType object. The System.Data.Metadata.Edm.EntityType.Members property is inherited from the StructuralType class. For more information about how to specify the members of the EntityType in a conceptual schema, see EntityType Element (CSDL).

  • System.Data.Metadata.Edm.EntityType.Properties: Gets a list of the properties of the EntityType object. For more information about how to specify the properties of the EntityType in a conceptual schema, see Entity Type (EDM) and EntityType Element (CSDL).

  • System.Data.Metadata.Edm.EntityType.NavigationProperties: Gets a list of the navigation properties of the EntityType object. For more information about how to specify the navigation properties of the EntityType in a conceptual schema, see Entity Type (EDM) and EntityType Element (CSDL).

  • System.Data.Metadata.Edm.EntityType.KeyMembers: Gets a list of the key members of the EntityType object. This property is inherited from the EntityTypeBase class.

  • System.Data.Metadata.Edm.RelationshipType.RelationshipEndMembers: Gets a list of the End members of the RelationshipType object.

  • System.Data.Metadata.Edm.AssociationType.AssociationEndMembers: Gets a list of the End members of the AssociationType object. For more information about how to specify the End members of the AssociationType in a conceptual schema, see Association Element (CSDL).

  • System.Data.Metadata.Edm.ComplexType.Properties: Gets a list of the properties of the ComplexType object. For more information about how to specify the properties of the ComplexType in a conceptual schema, see Complex Type (EDM) and How to: Define a Model with Complex Type (Entity Framework). The code sample in the ComplexType class demonstrates retrieving the properties of the complex types in the specified model.

The following code sample gets a metadata workspace from the connection and uses that metadata workspace to retrieve information about the members of the entity and relationship types in the specified model. Note that the metadata workspace is a runtime service component that provides support for retrieving metadata.

The code sample uses a CSpace to specify the model. The CSpace represents the default name for the conceptual model. The code sample uses the AdventureWorks model that is provided in AdventureWorks Complete Model (EDM) topic. For an example of the application config file, see Using the AdventureWorks Object Model (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

See Also

Concepts

Types (Metadata)
Metadata Type Hierarchy
Metadata Type Hierarchy Overview