Entity Data Model 101 - Part 2

Published 12 February 07 09:11 AM | dpblogs 

 

 

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

 

Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# Sam Gentile said on February 12, 2007 12:58 PM:

Found some time to blog. Smart Client/UI Architecture V2 of the User Interface Process Application Block

# Guy Burstein's Blog said on February 12, 2007 1:22 PM:

The ADO.Net team has published a serries of posts about the Entity Data Model (EDM) which is part of

# Frans Bouma said on February 12, 2007 1:25 PM:

Maybe I'm overlooking something, but why would you define relations on the entitytype and then AGAIN on the set using an associationSet ? Isn't that redundant?

# Eric Vincent said on February 13, 2007 2:03 PM:

Regarding "inheritance" in the database... what if the schema models inheritance where the sub-class has its own PK, and has an FK to the base clase (1:1 relation). For example, what if "Employee" had PK = EmployeeID int identity(1,1) and a FK ContactID int that referrs to the contact table's PK of ContactID int identity(1,1)?

Selection of Employees in this schema is by joining Contact and Employee, typically in a view. Is there a way to model the Employee object in CSDL / SSDL with this implementation? In the May06 CTP there didn't appear to be a way to handle this.

# Mike Dodaro said on February 13, 2007 2:17 PM:

For the moment let’s just consider many-to-many relationships. Recall that in the relational model, many-to-many relationships are realized by an intermediate “link” table, where each row of the link table holds a pair of foreign keys. Furthermore, a foreign key constraint in SQL must be scoped to a particular table.

Then, roughly speaking, the AssociationType definition specifies the shape of the link table, while the AssociationSet specifies the link table itself. When specifying the shape of a link table, we only need to know the types of the entities which may be related. However, when specifying the link table itself, we must also know which entity sets will hold those related entities.

If each defined entity type appears in at most one EntitySet definition, then you’re quite right: We could determine which entity sets must hold related entities from the AssociationType alone. However, when the same entity type is shared by multiple entity sets, we may need an AssociationSet to resolve the ambiguity.

We’ll try to eliminate redundant definitions in a future release, but for now we’re requiring everything to be defined explicitly.

# Frans Bouma said on February 14, 2007 10:15 AM:

"Then, roughly speaking, the AssociationType definition specifies the shape of the link table, while the AssociationSet specifies the link table itself. When specifying the shape of a link table, we only need to know the types of the entities which may be related. However, when specifying the link table itself, we must also know which entity sets will hold those related entities."

I consider myself not exactly a newbie on the front of O/R mapper development (I wrote one of the market leaders) however I have a hard time understanding what you're saying here.

What's the 'shape' of the link table? You mean by that the definition of the entity mapped onto the link table and the association set the DATA inside the link table ?

I still don't understand why you need an association set, because the relation is between 2 entities via an intermediate entity. That's already defined, so why using a different construct to define it AGAIN? Doesn't every entity instnace in a set has the relations its entity TYPE defined? If not, I really don't understand the necessity for this.  

I also find it hard to understand why you use an m:n example while the mapping file you posted contains no m:n relation which would justify the usage of the association set.

An entity set defines a set of entities, though by that it inherits the relations of the entity type of which instances are contained in the set (or am I thinking backwards?), so association sets of associations between sets is redundant, or at least odd, as the associations of the entities themselves already apply.

Or maybe I'm fundamentally not understanding something... Because: when are these associations used? Entity E1 is in set S1 and has a relation with entity E2, and E2 is in set S2 and in S3. I create instances of E1 and E2 in instances of sets S1 and S2 and S3. Because the definitions of E1 and E2 say they have a relation, why on earth do I have to define the relation AGAIN between S1 and S2/3? These are implicit, as E1 and E2 already have a relation defined.

Perhaps you should explain this more clearly in a follow up blogpost because how it's explained now is very obscure. I had a hard time following what you're saying in this post.

# Mike Dodaro said on February 14, 2007 3:13 PM:

RE: Regarding "inheritance" in the database... what if the schema models inheritance where the sub-class has its own PK, and has an FK to the base clase (1:1 relation)?

This is not supported mapping in current EDM.

# Mike Dodaro said on February 14, 2007 3:19 PM:

RE: AssociationType definition specifies the shape of the link table, while the AssociationSet specifies the link table itself.

I think of this in logical rather than structural terms.  In this sense the reason for declaration of both an Association and an AssociationSet is that the declaration of the Association defines an Assocation type while the AssocationSet specifies a logical container for instances of the Association.  Types and instances are fundamental to object oriented programming.  Declaring an EntityType or an Association in the Entity Data Model is analogous to declaring a class.  In programming languages a class defines the formal structure of a data type, but memory must be allocated to contain instances of the data type.  The Entity Data Model stores instances of entities and associations in a database, so instead of memory allocation, the association must be mapped to storage.  Declaration of the AssociationSet inside an EntityContainer provides the logical scope for instances of the Association.  This logical grouping of Association instances is mapped to storage structures using storage metadata and a mapping schema.  The storage metadata and mapping schemas will be discussed in future posts to this blog, or you can consult the documentation that ships with the February CTP release of ADO.NET.

# Douglas Husemann said on February 14, 2007 4:30 PM:

Know it probably won't be in version 1.  But I would like Temporal and Spacial support.

If this can be done through extentions that would be ok also.

thanks

# Frans Bouma said on February 14, 2007 4:47 PM:

Mike, ok. I had to re-read that reply a couple of times, so let me suggest that for the final documentation it's described in more layman's terms, although I am familiar with the theory behind o/r mapping, meta-data etc. (it's my job after all)

What I find odd still is why the association set inside a container is providing a scope for the association instances, while the association is declared in that same container... Perhaps it's useful in a situation which isn't covered by your example (likely) but I don't directly see the necessity of the association set declaration when I look at your example.

The February CTP isn't out yet, or is it released yet?

# Mike Dodaro said on February 14, 2007 10:06 PM:

Frans,

I had to call in the big guns to get to the bottom of this.  Abstract syntax is not my forte.  But, I have it on good authority that the real explanation runs as follows:

Let T and U be entity types.

Let TU be a relationship type from T to U.

Let ts be an entity set over entity type T.

Let us1 and us2 be entity sets over entity type U.

Let t be an entity within ts.

Now, in which set (us1 or us2) should we look to find the entity related to t? You could imagine that t would contain an indicator (say, the string “us1” or “us2”) to tell us which table to look at, but it’s difficult to enforce referential integrity in the underlying database if we allow that kind of flexibility. So instead, we require relationship set definitions to say, once and for all, where to look.

Putting this in laymans terms will be interesting.

# Writing about Programming, Programming about Writing said on February 15, 2007 12:44 AM:

Here are a few interesting blog posts. Eric White's Functional Programming Tutorial is a few months old

# Frans Bouma said on February 15, 2007 3:46 AM:

Mike: aha, I think we're getting closer. You see, I was thinking along these lines:

any entity instance related to t is referenced at runtime by t, so navigating to that related entity object is easy via the TU definition: it points you to the place where to look.

I think (bash me if I'm wrong) what you're describing here is more along the lines of: (bad metaphore up ahead, but it was as close as I could think of)

see the entity sets as datatables in a dataset and the associations in an association set as the datarelations between the datatables in a dataset. Am I close?

Because indeed, if you don't define the association set in _THAT_ situation, it's hard to define to which entity instance u a given t is related to because you have two sets with u's.

I was thinking along object references, as the entity framework from my point of view (POV) is seen as a way to perform o/r mapping, but that's of course not what you're working with, as the entity framework is a way to define entities on the level of an RDBMS.

I still find it a bit hard to understand why you have two association definitions though, as it seems to me at runtime one is unnecessary (i.e. the association defined on the entity itself, as it's meaningless IMHO, because without the association set definition, you can't find a related entity anyway)

# Mike Dodaro said on February 15, 2007 2:27 PM:

Frans,

Your intuition is right regarding relationship sets being like a little datasets holding the pairs of references.

We can’t just use relationship sets without also having relationship types because we want to be able to emit classes to describe entity types, which includes all the navigation properties needed for relationships on that entity type. We emit one class per entity type, not one class per entity set. Hence we need to know the “shape” of relationships (ie the names of their roles, the target multiplicities, and their target entity types) independently of both entity and relationship sets. This information is captured in the relationship type definition.

# ADO.NET team blog said on February 15, 2007 3:56 PM:

Most developers are familiar with the Object/Relational Mapping (ORM) problem: databases use the abstraction

# ADO.NET team blog said on February 26, 2007 2:39 PM:

Now that you’re getting accustomed to the Entity Framework and Entity Data Model ( Entity Data Model

# ADO.NET team blog said on May 10, 2007 4:38 PM:

Continuing along with posts on the essentials of Entity Framework mapping (see Mapping 101: Part 1 ),

# ADO.NET, LINQ, DataSet and other fun .NET technology said on August 3, 2007 4:18 PM:

I was recently asked what a high level list of good starting points for the Entity Framework is. This

# siriuslek said on August 9, 2007 10:41 AM:

Hi here how are you? I am newbie in blogs.msdn.com so i hope i will get some friends here :)

# Mike Taulty's Blog said on August 9, 2007 7:55 PM:

Note: Some of the posts referenced in this post (!) are likely to be more out of date than others but...

# James Hancock said on September 15, 2007 9:53 AM:

Hi all,

I've been reading your articles, and trying to figure out if .net entities will handle our case. It sounds like from the above that entities has the same limitation as Linq to SQL though...

All of our tables are setup like this:

ID (uniqueidentifier, PK)

Modified (datetime)

ModifiedByID (uniqueidentifier)

Changed (bit)

I need to build a base class that handles these fields and maintains their information on changes etc.

I then need to inherit from this base class and add additional properties and methods.

But from your explaination above, it appears that the base class must have a unique table name which won't work.

Is what I'm trying to do possible?

# BonzBlog Michaela Juřka said on September 17, 2007 3:07 PM:

Poslední reinkarnace LINQu, o které jsem se zmínil v přehledovém článku , je LINQ to ADO.NET Entities,

# BonzBlog Michaela Juřka said on September 17, 2007 3:08 PM:

Poslední reinkarnace LINQu, o které jsem se zmínil v přehledovém článku , je LINQ to ADO.NET Entities,

# Cristian's Blog said on October 3, 2007 4:08 AM:

SQL Server 2008 is at the door and the same stands for Visual Studio 2008. The data access strategy is

# Dating said on May 31, 2008 7:14 AM:

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”

# Weddings said on June 5, 2008 5:09 AM:

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”

# Sam Gentile's Blog said on December 3, 2008 10:21 AM:

Found some time to blog. Smart Client/UI Architecture V2 of the User Interface Process Application Block (UIPAB) is out from PAG [via Mike ]. I must confess to being confused on how this is different than CAB as &quot;designed to abstract the control

# Gaurav said on July 23, 2009 11:34 AM:

I'm connecting DB2 using DB2 .net provider. Inside the storage model under EntitySet element, there is an attribute called Schema which is hard coded with value of schema name from where that table came from. Now we have different schema name for various environment that we have like test, model, prod etc. How can change it at deployment time to point to correct schema.

please mail me at gaurav.vijaywargia@gmail.com

Leave a Comment

(required) 
(optional)
(required) 

  
Enter Code Here: Required

Search

This Blog

Syndication

Page view tracker