The Entity Data Model, an extended entity relationship model, is the core of the ADO.NET Entity Framework.
You can generate an Entity Data Model using the EDMGen.exe command line tool, or, using the ADO.NET Entity Data Model designer—a new Visual Studio template. We will discuss how an Entity Data Model can be generated from a relational schema in the next chapter.
The following figure illustrates where exactly the Entity Data Model fits in:
The Entity Data Model abstracts the logical or the relational schema and exposes the conceptual schema of the data using a three-layered approach. It is comprised of the following layers:
The Conceptual Data Definition Language Layer (C-Space)
The Mapping Schema Definition Language Layer (C-S Space)
The Store Space Definition Language Layer (S-Space)
The following figure illustrates the layers of the Entity Data Model:
The Conceptual Layer or the C-Space Layer is responsible for defining the entities and their relationships. It defines your business objects and their relationships in XML files. The C-Space is modeled using CSDL and is comprised of EntityContainer, EntitySets, AssociationSets, AssociationTypes, EntityTypes, and Functions. You can query this layer using Entity SQL or ESQL (EntityConnection, EntityCommand, and EntityDataReader).
The C-S Mapping Layer is responsible for mapping the conceptual and the logical layers. That is, it maps the business objects and the relationships defined in the conceptual layer with the tables and relationships defined in the logical layer. It is a mapping system created in XML, which links or maps the Conceptual and the Logical layers. The C-S Mapping layer is modeled using MSL.
The Logical or the Storage Layer (also called the S-Space) represents the schema of the underlying database. This is comprised of tables, stored procedures, view, and functions. It is modeled using SSDL and queried using ADO.NET Data Providers. Hence, we use SQLConnection, SQLCommand, SQLDataReader, and SQLDataAdapter using T-SQL or PL-SQL if our data store is a SQL database.
Here is how a typical Entity Data Model looks:
The Entity Data Model uses the following three types of XML files to represent the C-Space, C-S Space, and the S-Space respectively.
.CSDL (Conceptual Schema Definition Language): This represents the C-S Space and is used to map the entity types used in the conceptual model.
.MSL (Mapping Schema Language): This represents the C-S Space and is used to map the logical model to the conceptual model.
.SSDL (Store Schema Definition Language): This represents the S-Space and is used to map the schema information of the logical layer.
These files store the metadata information as XML for each of the above layers. Here is what the CSDL section of your Entity Data Model looks like:
<!-- CSDL content --> <edmx:ConceptualModels> <EntityContainer Name="PayrollEntities"> <EntitySet Name="Designation" EntityType="PayrollModel.Designation" /> </EntityContainer> <EntityType Name="Designation"> <Key> <PropertyRef Name="DesignationID" /> </Key> <Property Name="DesignationID" Type="Int32" Nullable= "false" /> <Property Name="DesignationName" Type="String" Nullable="false" MaxLength="50" Unicode="false" /> <NavigationProperty Name="Employee" Relationship= "PayrollModel.FK_Employee_Designation" FromRole="Designation" ToRole="Employee" /> </EntityType> </edmx:ConceptualModels>
Here is how a typical SSDL section of the Entity Data Model looks like:
<!-- SSDL content --> <edmx:StorageModels> <EntityContainer Name="dbo"> <EntitySet Name="Designation" EntityType= "PayrollModel.Store.Designation" /> </EntityContainer> <EntityType Name="Designation"> <Key> <PropertyRef Name="DesignationID" /> </Key> <Property Name="DesignationID" Type="int" Nullable="false" StoreGeneratedPattern="Identity" /> <Property Name="DesignationName" Type="varchar" Nullable="false" MaxLength="50" /> </EntityType> </Schema> </edmx:StorageModels>
And here is the C-S maping section for you:
<!-- C-S mapping content --> <edmx:Mappings> <Mapping Space="C-S" xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS"> <EntityContainerMapping StorageEntityContainer="dbo" CdmEntityContainer="PayrollEntities"> <EntitySetMapping Name="Designation"> <EntityTypeMapping TypeName="IsTypeOf(PayrollModel.Designation)"> <MappingFragment StoreEntitySet="Designation"> <ScalarProperty Name="DesignationID" ColumnName= "DesignationID" /> <ScalarProperty Name="DesignationName" ColumnName= "DesignationName" /> </MappingFragment> </EntityTypeMapping> </EntitySetMapping> </EntityContainerMapping> </Mapping> </edmx:Mappings> </edmx:Runtime> </edmx:Edmx>
Note
You can also create abstract and complex types in your Entity Data Model. You can derive from an abstract type to create sub-types, but no instance of the abstract type can be created. You can also create complex types. That is, types that don't have any identity of their own. A typical example of a complex type is the Address type.
We will skip further discussion on each of the sections of an Entity Data Model until Chapter 3.
When working with the ADO.NET Entity Framework, you will have an Object Model on top of all the Entity Data Model layers. You need to model the Object Model using .NET objects. The following figure illustrates how the Object Model fits in with the EDM layers:
The Object Model Layer contains, .NET objects, collection of .NET objects, types, properties and methods. You can use the Object Model or the O-Space Model to query your business objects, or the collections of your business objects, using LINQ to Entities or Entity SQL. The C-Space and O-Space models are actually mapped by the O-C Mapping Layer using code attributes applied to the O-space Model.
Language Integrated Query (LINQ) is a query translation pipeline that has been introduced as part of the C# 3.0 library. It comprises a set of query operators for different data sources (LDAP, Objects, CSV, XML, Entities, SQL, etc.). It is an extension of the C# language and provides a simplified framework for accessing relational data in a strongly typed, Object Oriented manner.
LINQ to Entities is a Microsoft technology that enables you to query your business objects from within the language in a strongly typed manner. You can use LINQ to Entities, a superset of LINQ to SQL, to query data against a conceptual data model, namely, the Entity Data Model. We will learn more on LINQ and LINQ to Entities in the chapter 6.
Here is an example of a typical LINQ to Entities query:
PayrollModel.PayrollEntities ctx = new PayrollModel.PayrollEntities(); var query = from emp in ctx.Employee select emp; foreach (var employee in query) Response.Write("<BR>"+employee.FirstName);
Entity Client, the gateway to entity-level queries, is the Entity Framework's counterpart of ADO.NET's SQL Client or Oracle Client that uses Entity SQL or E-SQL to query the conceptual model. You create a connection using Entity Connection, execute commands through Entity Commands, and retrieve the result sets as Entity Data Readers.
Entity SQL is a data store independent derivative of T-SQL that supports entity inheritance and relationships. You can use it to query data using the conceptual schema. You can even build your own dynamic queries. These E-SQL queries are internally translated to data store dependent SQL queries. This translation, that is, the conversion of the E-SQL queries to their data store-specific query language like T-SQL, (it doesn't need to be only T-SQL, however, it is the supported one) is handled by the Entity Framework. Entity SQL or E-SQL may not be as strongly typed as LINQ is, but, you have the flexibility of executing dynamic queries using it, much like T-SQL.
Note
Strongly typed data access is one of the most striking features of LINQ. LINQ queries are checked at compile time. This is unlike SQL queries which are only detected at runtime.
But, why do you need Entity SQL when you have LINQ to Entities to query data through you Entity Data Model? You can, using Entity SQL, compose queries that are difficult to determine until the time the query is executed. On a different note, Entity SQL is a full text-based query language that you can use in much the same way as you use ADO.NET data providers.
Here is an example that shows how you can use Entity SQL to insert data in your applications.
using (EntityConnection conn = new EntityConnection("Name=PayrollEntities")) { try { conn.Open(); EntityCommand cmd = conn.CreateCommand(); cmd.CommandText = "PayrollEntities.AddNewEmployee"; cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("FirstName", "Joydip"); cmd.Parameters.AddWithValue("LastName", "Kanjilal"); cmd.Parameters.AddWithValue("Address", "Hyderabad"); cmd.Parameters.AddWithValue("DepartmentID", 4); cmd.ExecuteNonQuery(); } catch (Exception ex) { Response.Write(ex.ToString()); } }
Note
To query data from the Entity Data Model, you have three choices—Entity SQL, LINQ to Entities, and Object Services.
You can use Entity SQL to avoid complex joins as you will typically be querying against a conceptual model of the data. As an example, if we want to display employee names and the department names in which they work, we would have to join the information of the Employee and the Department tables and then filter the unwanted columns to retrieve only the information that is required. Such traversals become a nightmare as you add additional tables and you therefore require more complex joins.
When you implement your Object Model using Object Oriented Programming Languages, you expose the object's relationships with other objects of its kind using properties. This is in contrast to the approach we just discussed. Hence, designing an Object Model using this approach is cumbersome. This is exactly where the ADO.NET Entity Framework fits in; it represents the conceptual and logical model of data while using grammar that is common to both.
Here is a code snippet that explains how you can use Entity SQL to avoid complex joins in your application's code. The following T-SQL query can be used to retrieve employee data split across three tables, namely, Employee, Department, and Salary.
Select Employee.FirstName, Employee.LastName, Department.DepartmentName, Salary.Basic from Employee INNER JOIN Department on Department.DepartmentID = Employee.DepartmentID INNER JOIN Salary on Salary.EmployeeID = Employee.EmployeeID
And, here is how you will use the Entity SQL to achieve the same result:
Select FirstName, LastName, DepartmentName, Basic from EmployeeData
Apart from querying the Conceptual Model, you might, at some point, have to work with entities such as in-memory objects or a collection of in-memory objects. To do this you need Object Services. You can use it to query data, from almost any data store, with less code. In addition to from enabling you to perform CRUD operations, the Object Services Layer provides the following additional services:
Change tracking
Lazy loading
Inheritance
Optimistic concurrency
Merging data
Identity resolution
Support for querying data using Entity SQL and LINQ to Entities
We will learn more about Object Services later in the book. The Object Services Layer internally uses an Object Query object for query processing. Note that the Object Services Layer supports querying data using both Entity SQL and LINQ to Entities.
Note
You can query data from the Entity Data Model either using Object Services or Entity Client. However, if you require change tracking, be aware that only Object Services provides this feature. Note that in either case, the ADO.NET Data Providers are responsible for talking to the underlying database.
Here is an example that shows how you can use Object Services to retrieve data.
Here is a quick look at some of the features and benefits of the ADO.NET Entity Framework:
Increased level of abstraction.
An extensible and flexible provider model.
Seamless querying of data using Entity SQL and LINQ.
A flexible schema for storing the mapping information.
Reduction to the amount of KLOC needed to write data access code in your applications.
Provides a layer of abstraction on top of any data store as long as an implementation for the underlying data store is provided.
A powerful Object Services Layer.
A full text-based query language.