Entity Framework: Part 1

The Entity Framework facilitates the development and conceptual use of application models for development instead of directly using relational storage schema.


The Entity Framework facilitates the development and conceptual use of application models for development instead of directly using relational storage schema. The benefits of conceptual programming models are fewer amounts of code and maintenance.

The ADO .NET Entity Framework provides the following benefits:

  • The Entity framework may help to remove hard-coded dependencies on storage schema.
  • EF provides mapping between conceptual model and storage schema; it helps to change storage schema without effecting application code.
  • Multiple conceptual models can be mapped to a single storage schema.
  • EF also supports LINQ for query; again the conceptual model helps us to provide compile time validation.

Entity Framework applications and services are XML- based language information divided into three parts:

  1. Conceptual Model (Conceptual schema definition language (CSDL)).
  2. Storage Model (Store schema definition language (SSDL))
  3. Mapping between Conceptual and Storage Model (Mapping specification language (MSL))

These three parts of the model can be generated automatically by the Entity Data Model Tool. This tool generates the model, mapping information as well as data classes from existing database schema. Developers can change the model using graphically change conceptual model with the help of the Entity Designer or change it manually by changing XML tags.

EntFrm1.jpg

The EDM Generator (EdmGen.exe) is a command-line tool used to generate a simple conceptual model with a one-to-one mapping between entities and tables in a data source. It can be used to validate a conceptual model and generate the data classes.

Before proceeding we must know the terminology of the Entity Framework. For that, refer to the following link.

http://msdn.microsoft.com/en-us/library/bb387161.aspx

Conceptual Model

The Conceptual model is also called Conceptual Schema Definition Language (CSDL) and is a XML based language. CSDL contains the entity type and each entity type has a name, a key (for uniquely identifying instances), and a set of properties. The Data Type of the properties are either a simple type (like int, string etc.) or complex type (like class, object etc.). XML attributes may also contain nullable or a default value. Associations define the relationships between entities.

Entity Relation in GUI.

EntFrm2.jpg

Finally, the Conceptual Model (CSDL) contains an Entity Set (Logical Name of Entity), Properties, keys (Primary Key) and associations.

Refer to the following figure to understand conceptual Model in detail.

EntFrm3.jpg

Storage Model

Storage model is also called a Storage Schema Definition Language (SSDL) and is also a XML based language. SSDL contain entity type (Actual Table name in Database in this case) and each entity type has a key (for Primary Key define in Database for that table), and a set of properties (Column of that database table). Properties of entity type contain name and type of column and nullable information.

EntFrm4.jpg

Mapping Model

Mapping model is also called Mapping Specification Language (MSL) and is a XML based language. MSL is a map of a conceptual model to a storage model.

EntFrm5.jpg

The EF compiles conceptual and storage model metadata, with mapping between Model and pair of entity SQL statements called "Client View". These views are generated invoked either at design time or runtime when query called first time in conceptual Model.

When the query is executed, its results are parsed and converted into a canonical command tree. This canonical command tree represents insert, update, delete and select commands. All subsequent processing is performed on the command tree that means communication between System.Data.EntityClient and data provider like System.Data.SqlClient.

Update EDMX

You can generate an EDM (Entity Data Model) using a database as a starting point or modify the XML manually or update it using a modeling tool.

You may update an edmx by generating it from the data base, but in the case where the model is very complicated and your conceptual model is totally different from the storage model, you must update your edmx manually.

First, we learn how we update the model using a builtin tool.

The first step is to open your EDMX in the GUI and right-click on EDMX and select "Update Model from Data Base."

EntFrm6.jpg

EntFrm7.jpg

From this screen you may add multiple tables, views and stored procedures. And click on the "Finish" button; it automatically generates a conceptual model and storage model in a XML file.

Update EDMX Manually

If you have large databases and your entity model is very customized then it is necessary to update the EDMX manually.

To update the EDMX manually, the first step is to open the EDMX with the XML Editor in Visual Studio.

Now we update the conceptual model, storage model and mapping model step by step.

The list of items must be updated to model work perfect (check list for updating model).

  1. Conceptual Model

    a. New Entity Type.
    b. Association (FOREIGN KEY).
    c. Entity set in Entity container.
    d. Add Association in Entity Container.
     
  2. Storage Model

    a. New Entity Type.
    b. Association (FOREIGN KEY).
    c. Entity set in Entity container.
    d. Add Association in Entity Container.
     
  3. Mapping Model

    a. Mapping Between Conceptual Model and Storage Model

Conceptual Model

Adding New Entity Type

<Schema Namespace="AdventureWorksModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
...
...
...

<EntityType Name="EmployeeAddress">
          <Key>
            <
PropertyRef Name="AddressId" />
          </Key>
          <
Property Type="Int32" Name="AddressId" Nullable="false" />
          <Property Type="Int32" Name="EmployeeId" />
          <Property Type="String" Name="AddressLine1" MaxLength="50" FixedLength="false" Unicode="false" />
          <Property Type="String" Name="AddressLine2" MaxLength="50" FixedLength="false" Unicode="false" />
          <Property Type="String" Name="AddressLine3" MaxLength="50" FixedLength="false" Unicode="false" />
          <Property Type="String" Name="City" MaxLength="50" FixedLength="false" Unicode="false" />
          <Property Type="String" Name="Pincode" MaxLength="10" FixedLength="false" Unicode="false" />
          <Property Type="String" Name="State" MaxLength="50" FixedLength="false" Unicode="false" />
          <Property Type="String" Name="Country" MaxLength="50" FixedLength="false" Unicode="false" />
          <NavigationProperty Name="Employee" Relationship="AdventureWorksModel.FK_Address_Employees" FromRole="EmployeeAddress" ToRole="Employee" />
        </EntityType>
....
....
....
 
</Schema>

Adding association

<Schema Namespace="AdventureWorksModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
....
....
....
<Association Name="FK_Address_Employees">
          <End Type="AdventureWorksModel.Employee" Role="Employee" Multiplicity="0..1" />
          <End Type="AdventureWorksModel.EmployeeAddress" Role="EmployeeAddress" Multiplicity="*" />
          <ReferentialConstraint>
            <
Principal Role="Employee">
              <PropertyRef Name="EmployeeId" />
            </Principal>
            <
Dependent Role="EmployeeAddress">
              <PropertyRef Name="EmployeeId" />
            </Dependent>
          </
ReferentialConstraint>
 </
Association>
....
....
....

</Schema>

Adding Entity Set in "Entity Container"

<Schema Namespace="AdventureWorksModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
        <EntityContainer Name="AdventureWorksEntities" annotation:LazyLoadingEnabled="true">
....
....
               
<EntitySet Name="EmployeeAddresses" EntityType ="AdventureWorksModel. EmployeeAddress" />

....
....
</EntityContainer>
....
....

</Schema>

Adding Association in "Entity Container".

<Schema Namespace="AdventureWorksModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation"
xmlns="http://schemas.microsoft.com/ado/2008/09/edm"
>
        <EntityContainer Name="AdventureWorksEntities" annotation:LazyLoadingEnabled="true">
....
....
               
<EntitySet Name="EmployeeAddresses" EntityType ="AdventureWorksModel. EmployeeAddress" />
<AssociationSet Name="FK_Address_Employees" Association="AdventureWorksModel.FK_Address_Employees">
            <End Role="Employee" EntitySet="Employees" />
            <End Role="EmployeeAddress" EntitySet="EmployeeAddresses" />
 </AssociationSet>

....
....
</EntityContainer>
....
....

</Schema>

Storage Model

Adding New Entity Type

<Schema Namespace="AdventureWorksModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
....
....
<EntityType Name="EmployeeAddress">
          <Key>
            <
PropertyRef Name="AddressId" />
          </Key>
          <
Property Name="AddressId" Type="int" Nullable="false" />
          <Property Name="EmployeeId" Type="int" />
          <Property Name="AddressLine1" Type="varchar" MaxLength="50" />
          <Property Name="AddressLine2" Type="varchar" MaxLength="50" />
          <Property Name="AddressLine3" Type="varchar" MaxLength="50" />
          <Property Name="City" Type="varchar" MaxLength="50" />
          <Property Name="Pincode" Type="varchar" MaxLength="10" />
          <Property Name="State" Type="varchar" MaxLength="50" />
          <Property Name="Country" Type="varchar" MaxLength="50" />
</EntityType>
....
....
</Schema>

Adding association

<Schema Namespace="AdventureWorksModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
....
....
<Association Name="FK_Address_Employees">
          <End Role="Employees" Type="AdventureWorksModel.Store.Employees" Multiplicity="0..1" />
          <End Role="EmployeeAddress" Type="AdventureWorksModel.Store.EmployeeAddress" Multiplicity="*" />
          <ReferentialConstraint>
            <
Principal Role="Employees">
              <PropertyRef Name="EmployeeId" />
            </Principal>
            <
Dependent Role="EmployeeAddress">
              <PropertyRef Name="EmployeeId" />
            </Dependent>
          </
ReferentialConstraint>
</
Association>
....
....
</Schema>

Adding Entity Set in "Entity Container"

<Schema Namespace="AdventureWorksModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
....
....
<EntityContainer Name="AdventureWorksModelStoreContainer">
....
....
               
<EntitySet Name="EmployeeAddress" EntityType="AdventureWorksModel.Store.EmployeeAddress" store:Type="Tables" Schema="dbo" />

....
....
</EntityContainer>
....
....
</Schema>

Adding Association in "Entity Container"

<Schema Namespace="AdventureWorksModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
....
....
<EntityContainer Name="AdventureWorksModelStoreContainer">
....
....
               
<EntitySet Name="EmployeeAddress" EntityType="AdventureWorksModel.Store.EmployeeAddress" store:Type="Tables" Schema="dbo" />
<AssociationSet Name="FK_Address_Employees" Association="AdventureWorksModel.Store.FK_Address_Employees">
            <End Role="Employees" EntitySet="Employees" />
            <End Role="EmployeeAddress" EntitySet="EmployeeAddress" />
          </AssociationSet>
....
....
</EntityContainer>
....
....
</Schema>

Mapping Model

<Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs">
        <EntityContainerMapping StorageEntityContainer="AdventureWorksModelStoreContainer" CdmEntityContainer="AdventureWorksEntities">
....
....
<EntitySetMapping Name="EmployeeAddresses">
            <EntityTypeMapping TypeName="AdventureWorksModel.EmployeeAddress">
              <MappingFragment StoreEntitySet="EmployeeAddress">
                <ScalarProperty Name="Country" ColumnName="Country" />
                <ScalarProperty Name="State" ColumnName="State" />
                <ScalarProperty Name="Pincode" ColumnName="Pincode" />
                <ScalarProperty Name="City" ColumnName="City" />
                <ScalarProperty Name="AddressLine3" ColumnName="AddressLine3" />
                <ScalarProperty Name="AddressLine2" ColumnName="AddressLine2" />
                <ScalarProperty Name="AddressLine1" ColumnName="AddressLine1" />
                <ScalarProperty Name="EmployeeId" ColumnName="EmployeeId" />
                <ScalarProperty Name="AddressId" ColumnName="AddressId" />
              </MappingFragment>
            </
EntityTypeMapping>
          </
EntitySetMapping>
 
....
....
</EntityContainerMapping>
</
Mapping>

In the next article we will learn about TPH (Table Per Hierarchy) and TPT (Table Per Type) and how to add it to an EDMX.

Reference

http://msdn.microsoft.com/en-us/library/bb399567.aspx