Entity Containers

In part one of this article we looked at declarations of entity and association types in conceptual schema definition language (CSDL). Now we have to be specific about where instances of those types are stored, which we refer to as “scope”. First, we must distinguish entity and association types from instances of those types. Instances of entity and association types exist as members of association sets, that is, EntityType and AssociationType define scope using EntitySet and AssociationSet declarations. Second, schema syntax specifies EntitySet and AssociationSet declarations inside an EntityContainer declaration. An EntityContainer collects the sets which should be logically grouped into a single database.

 

The EntityContainer segment of the CSDL schema is found in the following example. It shows the syntax for declaring an EntityContainer and its EntitySet and AssociationSet members. The EntityType and AssociationType declarations for Employee and Contact entities, as described in the previous post, can be found in the complete schema at the end of this post. In the following example an EntityContainer declares and defines EntitySet and AssociationSet members named in the plural forms Employees and Contacts.

 

The following syntax includes the declarations of an Employees EntitySet and two AssociationSet declarations. The first AssociationSet definition specifies End Role attributes of the Employee EntityType and Contact EntityType and then scopes the relationship to the Employees EntitySet and the Contacts EntitySet.

 

  <EntityContainer Name="AdventureWorks">

 

    <EntitySet Name="Employees" EntityType="AdventureWorksModel.Employee" />

 

    <EntitySet Name="Contacts" EntityType="AdventureWorksModel.Contact" />

 

    <AssociationSet Name="FK_Employee_Employee_ManagerID"

         Association="AdventureWorksModel.FK_Employee_Employee_ManagerID">

      <End Role="Employee" EntitySet="Employees" />

      <End Role="ManagedEmployee" EntitySet="Employees" />

    </AssociationSet>

 

    <AssociationSet Name="FK_Employee_Contact_ContactID"

         Association="AdventureWorksModel.FK_Employee_Contact_ContactID">

      <End Role="Contact" EntitySet="Contact" />

      <End Role="Employee" EntitySet="Employee" />

    </AssociationSet>

 

  </EntityContainer>

 

 

Every instance of an EntityType exists in a particular EntitySet. More than one EntitySet can be declared using a given EntityType. Every reference from one instance of an EntityType to another instance of an EntityType must be scoped to a defined EntitySet.

 

The logical sets of entities and associations defined by entity containers in the CSDL schema are used to build the namespace and classes of the programmable object model. There is a corresponding declaration in the storage schema that models the structure of data in storage. A mapping schema connects programmable classes to tables in storage.

 

Inheritance

The EDM supports single inheritance of entity types. This is the same idea as inheritance in object oriented programming. The Employee entity defined above can be the base type for various kinds of employees. A line-of-business application could require distinct types for employees in sales, accounting, customer service, maintenance, research, and technical support.

 

The following syntax derives a SalesEmployee entity from the BaseType Employee. It adds properties for ExpenseAccount and CarLicenseNumber. Note the absence of the Key property. The Key property of the derived type is the same as Key property of the base type. Any associations using a derived type must be declared on the base type because the derived type does not declare an entity set in the entity container. The entity set is needed to define the scope of an association using the derived type.

 

  <EntityType Type="SalesEmployee" BaseType="Employee" >

 

    <Property Name="ExpenseAccount" Type="Guid" Nullable="false" />

    <Property Name="CarLicenseNum" Type="String" Nullable="true" />

 

  </EntityType>

 

 

 

Complete CSDL Schema

The complete CSDL schema is declared in the following syntax.

 

<?xml version="1.0" encoding="utf-8"?>

<Schema Namespace="AdventureWorksModel"

    Alias="AdventureWorksModel"

      xmlns="http://schemas.microsoft.com/ado/2006/04/edm">

 

  <EntityType Name="Employee" Key="EmployeeID">

    <Property Name="EmployeeID" Type="Int32" Nullable="false" />

    <Property Name="NationalIDNumber" Type="String" Nullable="false"

         MaxLength="15" />

    <Property Name="LoginID" Type="String" Nullable="false"

         MaxLength="256" />

    <Property Name="Title" Type="String" Nullable="false"

         MaxLength="50" />

    <Property Name="BirthDate" Type="DateTime" Nullable="false" />

         MaxLength="1" FixedLength="true" />

    <Property Name="HireDate" Type="DateTime" Nullable="false" />

    <Property Name="SalariedFlag" Type="Boolean" Nullable="false" />

    <Property Name="VacationHours" Type="Int16" Nullable="false" />

 

    <NavigationProperty Name="Contact"

       Relationship="AdventureWorksModel.FK_Employee_Contact_ContactID"

        FromRole="Employee" ToRole="Contact" />

 

    <NavigationProperty Name="ManagedEmployee"

      Relationship="AdventureWorksModel.FK_Employee_Employee_ManagerID"

           FromRole="Employee"

           ToRole="ManagedEmployee" />

 

  </EntityType>

 

 

  <EntityType Name="Contact" Key="ContactID">

 

    <Property Name="ContactID" Type="Int32" Nullable="false" />

    <Property Name="NameStyle" Type="Boolean" Nullable="false" />

    <Property Name="Title" Type="String" MaxLength="8" />

    <Property Name="FirstName" Type="String" Nullable="false"

         MaxLength="50" />

    <Property Name="MiddleName" Type="String" MaxLength="50" />

    <Property Name="LastName" Type="String" Nullable="false"

         MaxLength="50" />

    <Property Name="Suffix" Type="String" MaxLength="10" />

    <Property Name="EmailAddress" Type="String" MaxLength="50" />

    <Property Name="EmailPromotion" Type="Int32" Nullable="false" />

    <Property Name="Phone" Type="String" MaxLength="25" />

    <Property Name="PasswordHash" Type="String" Nullable="false"

         MaxLength="128" />

    <Property Name="PasswordSalt" Type="String" Nullable="false"

         MaxLength="10" />

    <Property Name="rowguid" Type="Guid" Nullable="false" />

    <Property Name="ModifiedDate" Type="DateTime" Nullable="false" />

 

  </EntityType>

 

  <EntityType Type="SalesEmployee" BaseType="Employee" >

 

    <Property Name="ExpenseAccount" Type="Guid" Nullable="false" />

    <Property Name="CarLicenseNum" Type="String" Nullable="true" />

 

  </EntityType>

 

  <Association Name="FK_Employee_Employee_ManagerID">

    <End Role="Employee" Type="AdventureWorksModel.Employee" Multiplicity="0..1" />

    <End Role="ManagedEmployee" Type="AdventureWorksModel.Employee" Multiplicity="*"/>

  </Association>

 

  <Association Name="FK_Employee_Contact_ContactID">

    <End Role="Contact" Type="AdventureWorksModel.Contact" Multiplicity="1..1" />

    <End Role="Employee" Type="AdventureWorksModel.Employee" Multiplicity="*" />

  </Association>

 

 

  <EntityContainer Name="AdventureWorks">

 

    <EntitySet Name="Employees"

          EntityType="AdventureWorksModel.Employee" />

 

    <EntitySet Name="Contacts"

          EntityType="AdventureWorksModel.Contact" />

 

    <EntitySet Name="CreditCards"

          EntityType="AdventureWorksModel.CreditCard" />

 

    <AssociationSet Name="FK_Employee_Employee_ManagerID"

      Association="AdventureWorksModel.FK_Employee_Employee_ManagerID">

      <End Role="Employee" EntitySet="Employees" />

      <End Role="ManagedEmployee" EntitySet="Employees" />

    </AssociationSet>

 

    <AssociationSet Name="FK_Employee_Contact_ContactID"

       Association="AdventureWorksModel.FK_Employee_Contact_ContactID">

      <End Role="Contact" EntitySet="Contacts" />

      <End Role="Employee" EntitySet="Employees" />

    </AssociationSet>

 

  </EntityContainer>

 

</Schema>

 

 

Next Steps:

The EDM uses another schema similar to the one above to specify the storage metadata. The XML syntax used in the storage schema is called Storage Schema Definition Language (SSDL). The storage schema, or storage metadata, specifies the tables and columns of the database that correspond to entities and properties in the conceptual schema. An important difference between the SSDL schema and the CSDL schema is that SSDL syntax uses the data types of the database management system instead of the CLR types used in the CSDL schema.

In the SSDL schema, entity containers represent database structures. A mapping schema connects the entity containers and types defined in the CSDL schema to their corresponding tables and columns in the SSDL schema.  We'll discuss this in a future post.

 

Mike Dodaro

ADO.NET Programming Writer

 

Entity Data Model 101 - Part 1

 

Entity Data Model 101 - Part 3