Northwind Conceptual Schema (EDM)

Entity Data Model (EDM) entities and associations are the formal specifications for programmable objects in application code. With or without existing data, entities and associations are declared in conceptual schema definition language (CSDL) syntax. Writing a schema in CSDL is usually the first step in the design of an application built on the EDM.

The EDM application demonstrated in this and in neighboring topics uses existing data in the Northwind sample database, therefore the storage model is already implemented. Use of the data in this application requires attention to the structure of the existing tables when you define the entity types and associations in the domain of the application.

The implementation includes conceptual specifications, storage metadata, a mapping specification, and application code by using the object model built from the schemas and mapping specifications.

Four entities and two associations are defined by the schema example in this section. The entity types defined are derived from the base class schemas installed with ADO.NET. For an overview of schemas and mapping, see Schemas and Mapping Specification (Entity Framework).

In the following example, the opening <Schema> tag contains a declaration of the namespace being defined: NorthwindLib. The namespace has an alias, Self, that is used as a short identifier in the body of the schema. The URLs in the opening <Schema> tag are the same in all EDM applications.

<Documentation> tags include information useful to developers. The text between documentation tags is more than a code comment; after the object library has been built, the information appears in the object browser in Visual Studio and other tools that are used to browse classes. In this example, the text identifies the schema defined in this XML file.

Three entities in this example are defined within <EntityType> tags. Each entity includes a Key attribute indicating the property of the entity that is the unique identifier for instances of this type. Two <Association> types are specified by Name and End Role properties that provide scope for the types related by the associations. In this example, one association and navigation property connect instances of the Product entity with Category entities to which they are logically related. Another association connects Order instances with instances of Customers who make the orders. For more information about associations, see Entity Data Model Relationships.

<?xml version="1.0" encoding="utf-8"?>
<Schema xmlns:cg=https://schemas.microsoft.com/ado/2006/04/codegeneration
 xmlns:edm=https://schemas.microsoft.com/ado/2006/04/edm
 xmlns=https://schemas.microsoft.com/ado/2006/04/edm
 Namespace="NorthwindLib" Alias="Self">

  <EntityType Name="Product">
    <Key>
      <PropertyRef Name="ProductID" />
    </Key>
    <Property Name="ProductID" Type="Int32" Nullable="false" />
    <Property Name="ProductName" Type="String" 
                Nullable="false" ConcurrencyMode="Fixed" />
    <Property Name="UnitPrice" Type="Decimal" 
                Nullable="true" ConcurrencyMode="Fixed" />
    <NavigationProperty Name="Category"
          Relationship="Self.Category_Product" FromRole="Product"
          ToRole="Category" />
  </EntityType>

  <EntityType Name="DiscontinuedProduct" BaseType="Self.Product">
    <!-- Units in stock for discontinued products. -->
    <Property Name="UnitsInStock" Type="Int16" Nullable="true" />
  </EntityType>

  <EntityType Name="Customer">
    <Key>
      <PropertyRef Name="CustomerID" />
    </Key>
    <Property Name="CustomerID" Type="String" Nullable="false" />
    <Property Name="CompanyName" Type="String"
              Nullable="false" ConcurrencyMode="Fixed" />
    <Property Name="ContactName" Type="String"
              Nullable="true" ConcurrencyMode="Fixed" />
    <Property Name="City" Type="String"
              Nullable="true" ConcurrencyMode="Fixed" />
    <Property Name="Country" Type="String"
              Nullable="true" ConcurrencyMode="Fixed" />
    <NavigationProperty Name="SalesOrders"
            Relationship="Self.Customer_Order" FromRole="Customer"
            ToRole="SalesOrder" />
  </EntityType>

  <EntityType Name="Category">
    <Key>
      <PropertyRef Name="CategoryID" />
    </Key>
    <Property Name="CategoryID" Type="Int32" Nullable="false" />
    <Property Name="CategoryName" Type="String"
                  Nullable="false" ConcurrencyMode="Fixed" />
    <Property Name="Description" Type="String" Nullable="true" />
    <NavigationProperty Name="Products"
        Relationship="Self.Category_Product"
        FromRole="Category" ToRole="Product" />
  </EntityType>

  <EntityType Name="SalesOrder">
    <Key>
      <PropertyRef Name="OrderID" />
    </Key>
    <Property Name="OrderID" Type="Int32" Nullable="false" />
    <Property Name="OrderDate" Type="DateTime" Nullable="true" />
    <Property Name="ShipCity" Type="String" Nullable="true" />
    <Property Name="ShipCountry" Type="String" Nullable="true" />
    <NavigationProperty Name="Customer"
       Relationship="Self.Customer_Order"
       FromRole="SalesOrder" ToRole="Customer" />
  </EntityType>

  <Association Name="Customer_Order">
    <End Role="Customer" Type="Self.Customer" Multiplicity="1" />
    <End Role="SalesOrder" Type="Self.SalesOrder" Multiplicity="*" />
  </Association>

  <Association Name="Category_Product">
    <End Role="Category" Type="Self.Category" Multiplicity="1" />
    <End Role="Product" Type="Self.Product" Multiplicity="*" />
  </Association>

  <EntityContainer Name="Northwind">
    <EntitySet Name="Categories" EntityType="Self.Category" />
    <EntitySet Name="Products" EntityType="Self.Product" />
    <EntitySet Name="Customers" EntityType="Self.Customer" />
    <EntitySet Name="SalesOrders" EntityType="Self.SalesOrder" />
    <AssociationSet Name="CustomerOrders"
                  Association="Self.Customer_Order">
      <End Role="Customer" EntitySet="Customers" />
      <End Role="SalesOrder" EntitySet="SalesOrders" />
    </AssociationSet>
    <AssociationSet Name="CategoryProducts"
                  Association="Self.Category_Product">
      <End Role="Category" EntitySet="Categories" />
      <End Role="Product" EntitySet="Products" />
    </AssociationSet>
  </EntityContainer>

</Schema>

The most frequently used tags in this schema are <Property> tags. Properties specify the various kinds of data each <EntityType> contains. For example, the properties of a Product include the following: ProductID, ProductName, UnitPrice, and the NavigationProperty named Category that relates this product to a set of similar products. This group of properties defines the Product entity.

EDM <EntityContainer> tags specify a container that will be mapped to a database object (dbo) in the storage metadata schema. In this <EntityContainer>, there are three <EntitySet> specifications and two <AssociationSet> specifications.

For more information about the XML syntax used in this CSDL file, see Schemas (EDM). For information about navigation properties, see Implementing Associations (EDM).

See Also

Concepts

Entity Data Model Types
Entity Data Model Relationships
Schemas (EDM)
Implementing Associations (EDM)

Other Resources

Schemas and Mapping Specification (Entity Framework)