Partilhar via


Entity Data Model 101 - Part 2

 

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="https://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>

Comments

  • Anonymous
    February 12, 2007
    Found some time to blog. Smart Client/UI Architecture V2 of the User Interface Process Application Block

  • Anonymous
    February 12, 2007
    The ADO.Net team has published a serries of posts about the Entity Data Model (EDM) which is part of

  • Anonymous
    February 12, 2007
    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?

  • Anonymous
    February 13, 2007
    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.

  • Anonymous
    February 13, 2007
    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.

  • Anonymous
    February 14, 2007
    "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.

  • Anonymous
    February 14, 2007
    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.

  • Anonymous
    February 14, 2007
    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.

  • Anonymous
    February 14, 2007
    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

  • Anonymous
    February 14, 2007
    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?

  • Anonymous
    February 14, 2007
    The comment has been removed

  • Anonymous
    February 14, 2007
    Here are a few interesting blog posts. Eric White's Functional Programming Tutorial is a few months old

  • Anonymous
    February 14, 2007
    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)

  • Anonymous
    February 15, 2007
    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.

  • Anonymous
    February 15, 2007
    Most developers are familiar with the Object/Relational Mapping (ORM) problem: databases use the abstraction

  • Anonymous
    February 26, 2007
    Now that you’re getting accustomed to the Entity Framework and Entity Data Model ( Entity Data Model

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

  • Anonymous
    August 03, 2007
    The comment has been removed

  • Anonymous
    August 09, 2007
    Hi here how are you? I am newbie in blogs.msdn.com so i hope i will get some friends here :)

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

  • Anonymous
    September 15, 2007
    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?

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

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

  • Anonymous
    October 02, 2007
    SQL Server 2008 is at the door and the same stands for Visual Studio 2008. The data access strategy is

  • Anonymous
    May 30, 2008
    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”

  • Anonymous
    June 04, 2008
    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”

  • Anonymous
    December 03, 2008
    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

  • Anonymous
    July 23, 2009
    The comment has been removed

  • Anonymous
    April 22, 2010
    Hi, I'm starting to work with EDM in VS2010 but there is a problem, why the key must be Nullable="false"? This problem was in DataSet 2.0 too that nullable types are announced. When you create an instance of the EntityType, you don't have the Key values until they're load from data source. I think that the Nullability must be validate in SSDL not CSDL. If you create and instance of entity type, which value you should assign to the key to repesent not-assigned? null, -1, 0? (in case the Key is scalar int value)