Вы находитесь на странице: 1из 51

Entity Framework Notes

What is Entity Framework


Entity Framework is an ORM framework. ORM stands for Object Relational Mapping.

What is Object Relational Mapping framework


Object Relational Mapping framework automatically creates classes based on database tables, and the vice
versa is also true, that is, it can also automatically generate necessary SQL to create database tables based
on classes.

Installing NuGet Package Manager


1. From Visual Studio 2010 Tools menu, select Extension Manager
2. Click on Online Gallery in the Extension Manager window
3. Search for NuGet
4. Finally Download NuGet Package Manager and install

Please note: You must restart visual studio for the changes to take effect.

Step 2: Installing Entity Framework


a) Click on Tools - NuGet Package Manager - Manage NuGet Packages for solution
b) Click on "Online" tab in "Manage NuGet Packages" window
c) Type "EntityFramework" in the search textbox on the top right hand corner
d) Finally click on the "Install" button.

At this point Entity Framework version 6.1 is installed and a reference to EntityFramework assembly is also
automatically added.

1
Entity Framework Schema first Approach:
We want to display the above data from both the tables in a webform as shown below.

1. We need to create Department and Employee classes


2. Write ADO.NET code to retrieve data from the database
3. Once the data is retrieved we need to create Department and Employee objects and populate them with
data.

Step 1: Create a new "Empty ASP.NET Web Application" with name=Demo.

Step 2: Installing Entity Framework

Step 3: Create "Departments" and "Employees" tables.


Create table Departments
(
ID int primary key identity,
)
Create table Employees
(
ID int primary key identity,
DepartmentId int foreign key references Departments(Id)
)

Step 4: Populate the tables created in Step 3, with data


Insert into Departments values ('IT', 'New York')
Insert into Employees values ('John', 'Stanmore', 'Male', 80000, 1)

Step 5: Right click on the project in solution explorer and add ADO.NET Entity Data Model. Change the name
from Model1.edmx to EmployeeModel.edmx

Step 6: Select "Generate from database" and click "Next"

Step 7: Choose Your Data Connection


a) Click on "New Connection" button
b) Select "Microsoft SQL Server" as Data source, and ".Net Framework Data Provider for SQL

2
Server" option from "Data provider" dropdownlist. Click Continue.
c) On "Connection Properties" screen, specify SQL Server Name. If you are using local installation of SQL
Server then use (local) or . in the "server name" dropdownlist.
d) Specify the Authentication you want to use.
e) Select the database from "Select or enter database name" dropdownlist.
f) Finally "Test connection" and click "OK"
g) At this point we should be back on "Choose Your Data Connection" window. Make sure "Save entity
connection settings in Web.Config as" checkbox is selected and change the name of the connection string
to "EmployeeDBContext" and then Click"Next"

Step 8: On "Choose Your Database Objects" screen, select "Departments" and"Employees" tables. Change
the Model Namespace to "EmployeeModel" and click"Finish". At this point you should
have EmployeeModel.edmx created.

EmployeeModel.Designer.cs file is also generated. This file contains Employee and Department
classes. Tables are mapped to classes and columns are mapped to class properties.

Step 9: Add a webform. Drag and drop a GridView and an EntityDataSource control on the webform.

Step 10: Build the solution. Flip the WebForm1.aspx to design mode.
a) Right click on EntityDataSource control and select "Show smart tag" option from the context menu.
b) Click on "Configure Data Source" link
c) Select "Named Connection" radiobutton and select "EmployeeDBContext" from the dropdownlist.
d) Select "EmployeeDBContext" option from "DefaultContainerName" dropdownlist and click "Next"
e) On "Configure Data Selection" screen, select "Departments" from"EntitySetName" dropdownlist and
click "Finish"
f) Right click on "GridView1" control and select "Show smart tag" option.
g) Click on "Auto Format" link and select "Colorful" option from "AutoFormat" window and click "OK".
h) Select "EntityDataSource1" from "Choose Data Source" dropdownlist.
I) Click on "Eidt Columns" link and add a "Template Field". SetHeaderText=Employees and click OK.
j) Now click "Edit Templates" link.
k) Drag and drop a GridView control
l) Select "Edit DataBindings" link
m) Select "Custom binding" radiobutton and type Eval("Employees") in "Code expression" textbox and
click OK.
n) Select "End Template Editing" option from "GridView1" smart tasks pane.

Step 11: Right click on "EntityDataSource1" control and select "Properties". In properties window
set Include=Employees

3
Run the web application and notice that Departments and Employees are displayed as expected. We have
achieved all this without writing a single line of code.

In this demo, we have used schema first approach of entity framework.

Entity Framework Model First Approach:


In the Model First Approach, we first create the Entity Model. That is we create
1. Entities
2. Relationships between entities
3. Inheritance hierarchies etc.

We do all this directly on the design surface of the EDMX file.

Step 1: First delete the "EmployeeModel.edmx" file from the existing solution

Step 2: Add a new "ADO.NET Entity Data Model" file with name = EmployeeModel.

Step 3: On "Choose Model Contents" screen, select "Empty Model" and click"Finish"

Step 4: At this point, we have a blank EmployeeModel.edmx file added to the solution. Now, right click on
the designer surface and then select : Add - Entity. Set,
Entity Name = Department
Base Type = None
Entity Set = Departments
Create Key property = Select the check box
Property Name = Id
Property Type = Int32

Finally click OK.

4
Step 5: Right click on "Department" entity and select "Add - Scalar Property". Change the property name
to "Name". Right click on the "Name" property that we just added and select "properties" from the context
menu. Notice that the "Type" of "Name" property is set to "String".

Step 6: Similarly add "Location" property for the "Department" entity. At this point,
the"Department" entity should look as shown below.

Step 7: Add "Employee" entity and the following scalar properties.


FirstName (Type = string) LastName (Type = string)
Gender (Type = string)
Salary (Type = int)

Step 8: At this point, Department and Employee entities should look as shown below.

5
Step 9: We need to add "Employees" navigation property for the "Department" entity,
and "Department" navigation property for the "Employee" entity. To do this, right click on
the design surface and select "Add - Association". In the "Add Association" window, set values as shown in
the image below and click "OK"

Step 10: At this point, we should have the following created.


a) Employees navigation property in the Department entity
b) Department navigation property in the Employee entity
c) DepartmentId scalar property

Step 11: Right click on the design surface, and select "Generate Database from Model..." option

6
Step 12: On "Choose Your Data Connection" screen, click "Next"

Step 13: At this point, we should have the required SQL generated to create
a) Departments table
b) Employees table
c) Primary key constraints for Departments and Employees tables
d) Foreign key constraint
e) Indexes

Step 14: Click Finish. Now, we should have "EmployeeModel.edmx.sql" file generated with the required
SQL. If you already have "Departments" and "Employees" tables in the database, delete them. Right click on
the file and select "Execute SQL" option from the context menu.

Entity Framework Code First Approach:


Code-first approach allows us to create our custom classes first and based on those custom classes entity
framework can generate database automatically for us.

Step 1: Delete EmployeeModel.edmx && EmployeeModel.edmx.sql files from the solution explorer.

Step 2: Add a class file to the project. Name it Employee.cs. Copy and paste the following code.
public class Employee
{
// Scalar Properties
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public int Salary { get; set; }
// Navigation Property
public Department Department { get; set; }
}

Step 3: Add a class file to the project. Name it Department.cs. Copy and paste the following code.
public class Department
{
// Scalar Properties
public int Id { get; set; }
public string Name { get; set; }
public string Location { get; set; }
// Navigation Property
public List<Employee> Employees { get; set; }
}

Step 4: Add a class file to the project. Name it EmployeeDBContext.cs. Copy and paste the following code.
// EmployeeDBContext class must inherit from DbContext
// present in System.Data.Entity namespace
public class EmployeeDBContext : DbContext
{
public DbSet<Department> Departments { get; set; }
public DbSet<Employee> Employees { get; set; }
}

7
Step 5: Add a class file to the project. Name it EmployeeRepository.cs. Copy and paste the following code.
public class EmployeeRepository
{
public List<Department> GetDepartments()
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
return employeeDBContext.Departments.Include("Employees").ToList();
}
}

Step 6: Add the database connection string in web.config file.


<connectionStrings>
<add name="EmployeeDBContext"
connectionString="server=.; database=Sample; integrated security=true;"
providerName="System.Data.SqlClient"/>
</connectionStrings>

Please Note: If ProviderName is not specified the following runtime error will be thrown.
The connection string 'EmployeeDBContext' in the application's configuration file does not contain the
required providerName attribute."
Step 7: Configure Object Data Source control
a) Delete EntityDataSource control, that is already there in WebForm1.aspx.
b) Drag and Drop ObjectDataSource control.
c) Right click on ObjectDataSource control and select "Show Smart Tag" option from the context menu
d) Click on "Configure Data Source..." link
e) On "Choose a Business Object" screen, select "EmployeeRepository" and click"Next"
f) On "Define Data Methods" screen, select GetDepartments() method and click"Finish"

Step 8: Configure GridView control


a) Right click on GridView control and select "Show Smart Tag" option from the context menu
b) Select "ObjectDataSource1" from "Choose Data Source" dropdownlist
c) Click "No" to "Refresh Fields and Keys for GridView1" when prompted

Step 9: Rebuild the solution.


Step 10: Delete the already existing database from SQL Server Management Studio.
Step 11: Run the application by pressing CTRL + F5. Notice that we don't have any data displayed on
WebForm1. This is because we don't have any data in the Departments and Employees tables. At this point
we have the following created automatically.
a) Sample database
b) Departments table
c) Employees table

Customizing table, column and foreign key column names when using
entity framework code first approach:
Entity Framework generated the following Employees table. Notice the column
names.Department_Id column has an underscore in it's name. Let's say we want the column to be
generated as DepartmenId (without an underscore)

8
To achieve this use the ForeignKey attribute present
inSystem.ComponentModel.DataAnnotations.Schema namespace. Modify the Employee class as shown
below.
public class Employee
{
public int DepartmentId { get; set; }
[ForeignKey("DepartmentId")]
public Department Department { get; set; }
}

Rebuild the solution, and run the application.


You will get the following error. We will discuss the reasons for this error and how to fix it the right way in a
later video session.
The model backing the 'EmployeeDBContext' context has changed since the database was created. Consider
using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).

For now to get around the error, delete the Sample database using SQL Server Management Studio, and
then try to run the application again. A blank webform will be displayed. Now check the Employees tables
using SQL Server Management Studio and notice that the DepartmentId column is created without an
underscore as expected.

To customize the table name, use Table attribute and to customize column name useColumn attribute.

For example, to change


Table name from Employees to tblEmployees and
FirstName column to First_Name
We would modify the Employee class as shown below.
[Table("tblEmployees")]
public class Employee
{
public int Id { get; set; }
[Column("First_Name")]
public string FirstName { get; set; }
public int DepartmentId { get; set; }
[ForeignKey("DepartmentId")]
public Department Department { get; set; }

9
}
Entity Framework would then generate the following. Notice the table name andFirst_Name column.

How to handle model changes in entity framework:


Now let us add JobTitle property to the Employee class. The modified Employee class is shown below.
[Table("tblEmployees")]
public class Employee
{
public int DepartmentId { get; set; }
[ForeignKey("DepartmentId")]
public Department Department { get; set; }
public string JobTitle { get; set; }
}

At this point if we run the application, we get the following error.


The model backing the 'EmployeeDBContext' context has changed since the database was created. Consider
using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).

This is because the model (i.e Employee class) has changed since the database was created. This means the
Model and the database are no longer in sync and hence we get the error. To check if the model has
changed since the database was created, entity framework uses __MigrationHistory table that is auto-
generated.

To fix this error, we have to tell entity framework what to do when the model changes.

Add Global.asax file to the web application project. Include the following code in Application_Start ()
method. Here, we are telling the entity framework to drop and recreate database every time the model
changes.
Database.SetInitializer (new DropCreateDatabaseIfModelChanges<EmployeeDBContext> ());

Another option is, to drop and recreate the database always. To drop and recreate the database always we
would change the code in Application_Start () method as shown below.
Database.SetInitializer (new DropCreateDatabaseAlways<EmployeeDBContext> ());
Please Note: Database class is present in System.Data.Entity namespace.

How to seed database with test data using entity framework:


We have been manually populating the database with test data using the insert sql script. Entity Framework
can automate this. Here are the steps.

Step 1: Right click on the project in solution explorer and add a class file with name
=EmployeeDBContextSeeder.cs

Step 2: Copy and paste the following code in EmployeeDBContextSeeder.cs file

10
using System.Collections.Generic;
using System.Data.Entity;
namespace EntityFrameworkDemo
{
public class EmployeeDBContextSeeder :
DropCreateDatabaseIfModelChanges<EmployeeDBContext>
{
protected override void Seed(EmployeeDBContext context)
{
Department department1 = new Department()
{
Name = "IT",
Location = "New York",
Employees = new List<Employee>()
{
new Employee()
{
FirstName = "John",
LastName = "Stanmore",
Gender = "Male",
Salary = 80000,
JobTitle = "Project Manager"
}
}
};

Department department2 = new Department()


{
Name = "HR",
Location = "London",
Employees = new List<Employee>()
{
new Employee()
{
FirstName = "Mary",
LastName = "Lambeth",
Gender = "Female",
Salary = 30000,
JobTitle = "Sr. Recruiter"
}
}
};
context.Departments.Add(department1);
context.Departments.Add(department2);
base.Seed(context);
}
}
}

11
Step 3: Copy and paste the following line in Application_Start() method Global.asax file
Database.SetInitializer(new EmployeeDBContextSeeder());

Step 4: Remove the following Table and Column attributes from Employee.cs file.
[Table("tblEmployees")]
[Column("First_Name")]

Using stored procedures with entity framework:


our own custom stored procedures to perform Insert, Update and Delete operations using entity
framework.

Step 1: Use the following SQL Script to create and populate Employee table.

Step 2: Create Insert, Update and Delete stored procedures


Create procedure InsertEmployee
@Name nvarchar(50),
@Gender nvarchar(50),
@Salary int
as
Begin
Insert into Employees values (@Name, @Gender, @Salary)
End
Go
Step 3: Create a new empty asp.net web application

Step 4: Add a new ADO.NET Entity Data Model.


a) On Choose Model Contents screen select "Generate from database" option and click Next
b) On "Choose Your Data Connections" screen give a meaningful name for the connection string that will be
stored in the web.config file. I have named itEmployeeDBContext. Click Next.

c) On "Choose Your Database Objects" screen, select Employees Table and the 3 stored procedures
(InsertEmployee, UpdateEmployee, DeleteEmployee). Provide a meaningful name for the Model
namespace. I have named it EmployeeModel. ClickFinish.

At this point on the ADO.NET Entity Model designer surface, we should be able to see the
Employee entity but not the stored procedures.

To view the stored procedures,


1. Right click on entity model designer surface and select "Model Broswer" from the context menu.
2. Expand Stored Procedures folder

12
Step 5: Add a web form to the project. Drag and drop the following 3 controls and build the solution.
1. GridView
2. DetailsView
3. EntityDataSource

Step 6: Configure EntityDataSource control

a). Right click on EntityDataSource control and select "Show Smart Tag" option

b) Click on Configure Data Source link

c) Select EmployeeDBContext from the Named Connection dropdownlist and click Next

d) Select the options on "Configure Data Selection" screen as shown in the image below and click Finish

Step 7: Configure GridView control

a). Select "EntityDataSource1" from "Choose Data Source" dropdownlist

b) Select Enable Editing and Enable Deleting checkboxes

13
Step 8: Configure DetailsView control
a) Select "EntityDataSource1" from "Choose Data Source" dropdownlist
b) Select Enable Inserting checkbox
c) Set DeafultMode=Insert. Use properties window to set this.
d) Set InsertVisible="false" for the ID BoundField. You can do this directly in the HTML Source.
e) Generate ItemInserted event handler method for DetailsView control. Copy and paste the following code.
protected void DetailsView1_ItemInserted (object sender, DetailsViewInsertedEventArgse)
{
GridView1.DataBind();
}

At this point if you run the application, and if you insert, update and delete employees, by default entity
framework will use the sql it auto-generates and not our custom stored procedures.

To tell the entity framework to use the stored procedures, we have to map them to the Employee entity.

Here are the steps.


1. Right click on "Employee" entity on "EmployeeModel.edmx" and select "Stored Procedure
Mapping" option from the context menu.

2. In the "Mapping Details" windows specify the Insert, Update and Delete stored procedures that you
want to use with "Employee" entity

At this point,
1. Run SQL Prrofiler
2. Run the application
3. Insert, Update and Delete Employee, and notice that the respective stored procedures are being called
now.

Using stored procedures with entity framework code first approach:


using stored procedures to perform Insert, Update and Delete operations using entity framework code
first approach.

14
Step 1: Create a new empty asp.net web application project. Name it Demo. Install entity framework if it's
not already installed.
Step 2: Add a class file to the project. Name it Employee.cs. Copy and paste the following code.
public class Employee
{
//Some Properties
}
Step 3: Add a class file to the project. Name it EmployeeDBContext.cs. Copy and paste the following code.
using System.Data.Entity;
public class EmployeeDBContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// This line will tell entity framework to use stored procedures
// when inserting, updating and deleting Employees
modelBuilder.Entity<Employee>().MapToStoredProcedures();
base.OnModelCreating(modelBuilder);
}
}

Step 4: Add a class file to the project. Name it EmployeeRepository.cs. Copy and paste the following code.
using System.Collections.Generic;
using System.Linq;
public class EmployeeRepository
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
public List<Employee> GetEmployees()
{
return employeeDBContext.Employees.ToList();
}
public void InsertEmployee(Employee employee)
{
employeeDBContext.Employees.Add(employee);
employeeDBContext.SaveChanges();
}
public void UpdateEmployee(Employee employee)
{
Employee employeeToUpdate = employeeDBContext .Employees.SingleOrDefault(x => x.ID ==
employee.ID);
employeeToUpdate.Name = employee.Name;
employeeToUpdate.Gender = employee.Gender;
employeeToUpdate.Salary = employee.Salary;
employeeDBContext.SaveChanges();
}
public void DeleteEmployee(Employee employee)
{
Employee employeeToDelete = employeeDBContext.Employees.SingleOrDefault(x => x.ID == employee.ID);

15
employeeDBContext.Employees.Remove(employeeToDelete);
employeeDBContext.SaveChanges();
}
}

Step 5: Add the database connection string in web.config file.


<add name="EmployeeDBContext"
connectionString="server=.; database=Sample; integrated security=true;"
providerName="System.Data.SqlClient" />
Step 6: Add a webform to the project. Drag and drop the following 3 controls and build the solution.
1. GridView 2. DetailsView 3. ObjectDataSource

Step 7: Configure ObjectDataSource control


a) Select Demo.EmployeeRepository on Choose a Business Object screen and click Next
b) On Define Data Methods screen
i) On SELECT tab - Select GetEmployees() method
ii) On UPDATE tab - Select UpdateEmployees(Employee employee) method
iii) On INSERT tab - Select InsertEmployees(Employee employee) method
iv) On DELETE tab - Select DeletEmployees(Employee employee) method

Step 8: Configure GridView control


a) Select "ObjectDataSource1" from "Choose Data Source" dropdownlist
b) Select Enable Editing and Enable Deleting checkboxes
c) Set DataKeyNames="ID". Do this in the properties window of the GridView control

Step 9: Configure DetailsView control


a) Select "ObjectDataSource1" from "Choose Data Source" dropdownlist
b) Select Enable Inserting checkbox
c) Set DeafultMode=Insert. Use properties window to set this.
d) Set InsertVisible="false" for the ID BoundField. You can do this directly in the HTML Source.

Step 10: If you already have Sample database in SQL Server. Delete it from SQL Server Management Studio.

Step 11: Run the application by pressing CTRL + F5. Notice that we don't have any data displayed on
WebForm1. This is because we don't have any data in the Employees table.

At this point we have the Sample database and Employees table created automatically. The following stored
procedures are also automatically created.
Employee_Delete
Employee_Insert
Employee_Update

By default, the following should be the naming convention for the stored procedures.
INSERT stored procedure - [Entity_Name]_Insert. Insert Stored procedure should return the auto-generated
identity column value.
UPDATE stored procedure - [Entity_Name]_Update
DELETE stored procedure - [Entity_Name]_Delete

At this point,
1. Run SQL Profiler
2. Run the application
3. Insert, Update and Delete Employees, and notice that the respective stored procedures are being called as
expected.

16
Overriding stored procedure defaults with entity framework code first
approach:
If you want to override or change the default names of auto-generated stored procedures, change the code
,The default parameter names of the stored procedures can also be changed in EmployeeDBContext class
as shown below.

public class EmployeeDBContext : DbContext

{
public DbSet<Employee> Employees { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>().MapToStoredProcedures
(p => p.Insert(i => i.HasName("InsertEmployee")
.Parameter(n => n.Name, "EmployeeName")
.Parameter(n => n.Gender, "EmployeeGender")
.Parameter(n => n.Salary, "EmployeeSalary"))
.Update(u => u.HasName("UpdateEmployee")
.Parameter(n => n.ID, "EmployeeID")
.Parameter(n => n.Name, "EmployeeName")
.Parameter(n => n.Gender, "EmployeeGender")
.Parameter(n => n.Salary, "EmployeeSalary"))
.Delete(d => d.HasName("DeleteEmployee")
.Parameter(n => n.ID, "EmployeeID"))
);
base.OnModelCreating(modelBuilder);
}
}
At this point drop the Sample database and run WebForm1 again. Notice that the stored procedure
parameters have the names we specified.

17
Entity splitting in entity framework:
Entity splitting refers to mapping an entity to two or more tables when the tables share a common key.

Now, when we use ADO.NET Entity Framework to generate entities from the database using database first
approach, by default 2 entities will be created, i.e Empoyee andEmployeeContactDetail entities.

There is a one to one mapping between tables and entities. We want a singleEmployee to map to
both Employees & EmployeeContactDetails table.

To achieve this
1. Cut Email, Mobile and LandLine properties from EmployeeContactDetail entity and paste them
in Employee entity
2. Delete EmployeeContactDetail entity. On "Delete Unmapped Tables and Views"window click NO.
3. Right click on Employee entity and select "Table Mapping" option from the context menu.
Map EmployeeId, Email, Mobile and LandLine properties to the respective columns
of EmployeeContactDetails table.

At this point we have only one Entity. Build the solution. Add a WebForm.
Configure EntityDataSource control
c) Select EmployeeDBContext from the Named Connection dropdownlist and clickNext
d) Select Employees from EntitySetName dropdownlist and enable Inserts, Updatesand Deletes.

Configure GridView control


Configure DetailsView control

18
At this point run the application. Insert, update and delete an Employee, and notice that both the tables
(Employees and EmployeeContactDetails) are updated as expected.

Entity splitting in entity framework with code first approach:


Step 1: Create a new empty asp.net web application project. Name it Demo. Install entity framework if it's
not already installed.

Step 2: Add a class file to the project. Name it Employee.cs. Copy and paste the following code.
public class Employee
{
// These property values should be stored in Employees Table
public int EmployeeId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }

// These property values should be stored in EmployeeContactDetails Table


public string Email { get; set; }
public string Mobile { get; set; }
public string Landline { get; set; }
}

Step 3 to 10 : Follow the steps like in page no: 13,14

Step 11: Run the application by pressing CTRL + F5. By default entity framework creates one Table i.e
Employees table. But we want entity framework to create the following 2 tables.
a) Employees table with columns EmployeeId, FirstName, LastName and Gender
b) EmployeeContactDetails table with columns EmployeeId, Email, Mobile and Landline

Step 12: Override OnModelCreating() method to tell entity framework to generate 2


tables(Employees & EmployeeContactDetails) for the Employee entity.OnModelCreating() method is
a virtual method present in DbContext class. So, modifyEmployeeDBContext class
in EmployeeDBContext.cs file as shown below.
public class EmployeeDBContext : DbContext
{
public DbSet<Employee> Employees { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)


{
modelBuilder.Entity<Employee>()
// Specify properties to map to Employees table
.Map(map =>
{
map.Properties(p => new
{
p.EmployeeId, p.FirstName, p.LastName, p.Gender
});
map.ToTable("Employees");
})

19
// Specify properties to map to EmployeeContactDetails table
.Map(map =>
{
map.Properties(p => new
{
p.EmployeeId, p.Email,p.Mobile,p.Landline
});
map.ToTable("EmployeeContactDetails");
});
base.OnModelCreating(modelBuilder);
}
}

Step 13: Delete the Sample database and run the web application.

Step 14: Notice that now we have 2 tables generated by entity framework as expected.

Table splitting in entity framework Data Base First:


Mapping multiple entities to a single table is called table splitting.

20
One common entity framework interview question is, What is the main reason for using Table Splitting?
Table Splitting is useful when you want to delay the loading of some properties with large data when using
lazy loading.

For example, if you have Employee entity and if it contains Photo property that would return large binary
data, and if we use this Photo property only on a few pages in our application, then it does not make sense
from a performance perspective to load this property every time we load the Employee entity. Using lazy
loading load it only on the pages where we need to display Employee photo.

SQL script to create the table


Create table Employees
(
EmployeeID int primary key identity,
FirstName nvarchar(50),
LastName nvarchar(50),
Gender nvarchar(50),
Email nvarchar(50),
Mobile nvarchar(50),
LandLine nvarchar(50)
)

Now, when we use ADO.NET Entity Framework to generate entities from the database using database first
approach, by default one entity will be created, i.e Empoyee entity.

Let's say, we will not be using Email, Mobile and Landline properties as often as we would be
using FirstName, LastName, and Gender properties. If all of these properties are present in one Employee
entity, then every time we load this entity, all the properties will be automatically loaded. So let's create 2
entities (Employee & EmployeeContactDetail). This enables us to load EmployeeContactDetails only when
needed.

To achieve this:
1. Right click on the entity designer and select "Add Entity" option from the context menu. Set
a) Entity Name = EmployeeContactDetail
b) Bae type = (None)
c) Entity Set = EmployeeContactDetails
d) Create Key Property = Checked
e) Property Name = EmployeeID

21
2. Cut Email, Mobile and LandLine properties from Employee entity and paste them
inEmployeeContactDetail entity

3. Right click on the entity designer and select "Add - Association" option from the context menu. Fill the
details shown below.

4. Right click on the association and select "Properties". In the Properties window, click on
the ellipsis button next to "Referential Constraint" property and fill in the details as shown below.

5. Right click on "EmployeeContactDetail" entity and select "Table Mapping" option from the context
menu. Select "Employees" table and map EmployeeId, Email, Mobileand Landline properties of the entity
to the respective columns of the table.

22
6. Add a webform. Copy and paste the following HTML in the ASPX page.
<div style="font-family:Arial">
<asp:CheckBox ID="checkBoxIncludeContactDetails"
Text="Include Contact Details" runat="server" />
<br />
<asp:Button ID="Button1" runat="server" Text="Get Employee Data"
onclick="Button1_Click" />
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
</div>

7. Copy and paste the following code in the code-behind file.


private DataTable GetEmployeeData()
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
List<Employee> employees = employeeDBContext.Employees.ToList();

DataTable dataTable = new DataTable();


DataColumn[] columns = { new DataColumn("EmployeeID"), new DataColumn("FirstName"),
new DataColumn("LastName"), new DataColumn("Gender")};
dataTable.Columns.AddRange(columns);
foreach (Employee employee in employees)
{
DataRow dr = dataTable.NewRow();
dr["EmployeeID"] = employee.EmployeeID; dr["FirstName"] = employee.FirstName;
dr["LastName"] = employee.LastName; dr["Gender"] = employee.Gender;
dataTable.Rows.Add(dr);
}
return dataTable;
}
private DataTable GetEmployeeDataIncludingContactDetails()
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
List<Employee> employees = employeeDBContext.Employees
.Include("EmployeeContactDetail").ToList();
DataTable dataTable = new DataTable();

23
DataColumn[] columns = { new DataColumn("EmployeeID"), new DataColumn("FirstName"),
new DataColumn("LastName"), new DataColumn("Gender"),
new DataColumn("Email"), new DataColumn("Mobile"),
new DataColumn("LandLine") };
dataTable.Columns.AddRange(columns);
foreach (Employee employee in employees)
{
DataRow dr = dataTable.NewRow();
dr["EmployeeID"] = employee.EmployeeID; dr["FirstName"] = employee.FirstName;
dr["LastName"] = employee.LastName; dr["Gender"] = employee.Gender;
dr["Email"] = employee.EmployeeContactDetail.Email;
dr["Mobile"] = employee.EmployeeContactDetail.Mobile;
dr["LandLine"] = employee.EmployeeContactDetail.LandLine;
dataTable.Rows.Add(dr);
}
return dataTable;
}
protected void Button1_Click(object sender, EventArgs e)
{
if (checkBoxIncludeContactDetails.Checked)
{
GridView1.DataSource = GetEmployeeDataIncludingContactDetails();
}
else
{
GridView1.DataSource = GetEmployeeData();
}
GridView1.DataBind();
}
At this point, run the application and when you retrieve Employees without checking"Include Contact
Details" checkbox, the following query is generated by the entity framework. Use SQL Profiler to view the
generated query. Notice that Email, Mobile andLandLine column values are not loaded.
SELECT
[Extent1].[EmployeeID] AS [EmployeeID],[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],[Extent1].[Gender] AS [Gender]
FROM [dbo].[Employees] AS [Extent1]

When you check "Include Contact Details" checkbox, the following query is generated
SELECT
[Extent1].[EmployeeID] AS [EmployeeID],[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],[Extent1].[Gender] AS [Gender],
[Extent1].[Email] AS [Email],[Extent1].[Mobile] AS [Mobile],[Extent1].[LandLine] AS [LandLine]
FROM [dbo].[Employees] AS [Extent1]
Table splitting in entity framework with code first approach:
Mapping multiple entities to a single table is called table splitting.

Step 1: Create a new empty asp.net web application project. Name it Demo. Install entity framework if it's
not already installed.

24
Step 2: Add a class file to the project. Name it Employee.cs. Copy and paste the following code.
public class Employee
{
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }

public EmployeeContactDetail EmployeeContactDetail { get; set; }


}

Step 3: Add a class file to the project. Name it EmployeeContactDetail.cs. Copy and paste the following
code.
public class EmployeeContactDetail
{
public int EmployeeID { get; set; }
public string Email { get; set; }
public string Mobile { get; set; }
public string LandLine { get; set; }
public Employee Employee { get; set; }
}
Step 4: Add a class file to the project. Name it EmployeeDBContext.cs. Copy and paste the following code.
using System.Data.Entity;
public class EmployeeDBContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.HasKey(pk => pk.EmployeeID) .ToTable("Employees");

modelBuilder.Entity<EmployeeContactDetail>()
.HasKey(pk => pk.EmployeeID) .ToTable("Employees");

modelBuilder.Entity<Employee>()
.HasRequired(p => p.EmployeeContactDetail).WithRequiredPrincipal(c => c.Employee);
}
}
Step 5: Add the database connection string in web.config file.
<connectionStrings>
<add name="EmployeeDBContext"
connectionString="server=.; database=Sample; integrated security=SSPI;"
providerName="System.Data.SqlClient" />
</connectionStrings>

Step 6, 7 : Go to page 23,24


At this point, run the application. Sample database and Employees table should be created by the entity
framework.

25
Conditional Mapping in entity framework Database First:
We will be using the following Employees table in this demo. IsTerminated column determines if an
employee is a terminated employee or not.

SQL Query to create Employees table


If the application that we are developing always need only the employees who are not terminated, then in
the query we will have to always include the filter across our entire application. Conditional Mapping can be
used to apply such a permanent filter on the entity, so that the generated SQL query always have the WHERE
clause.

To use Conditional Mapping,


1. Right click on the entity and select "Table Mapping" option from the context menu
2. Add the condition - When Is Terminated = false

At this point, if you build the solution or validate the model, you will get the following error
Problem in mapping fragments starting at line 46:Condition member 'Employees.IsTerminated' with a
condition other than 'IsNull=False' is mapped. Either remove the condition on Employees.IsTerminated or
remove it from the mapping

This is because, a table column cannot be mapped more than once. We have usedIsTerminated column
in conditional mapping, so it cannot be used in property mapping as well. For this reason delete it from
Employee entity.

Add a web form to the project. Drag and drop a GridView control. Copy and paste the following code in the
code-behind file.
protected void Page_Load(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
GridView1.DataSource = employeeDBContext.Employees;
GridView1.DataBind();
}

Open SQL profiler and run the webform. Notice that the select query has a whereclause, which will always
return employees who are not terminated.

26
Conditional Mapping in entity framework with code first:
Conditional Mapping in entity framework with code first approach.

Step 1: Create a new empty asp.net web application project. Name it Demo. Install entity framework if it's
not already installed.

Step 2: Add a class file to the project. Name it Employee.cs. Copy and paste the following code.
public class Employee
{
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public bool IsTerminated { get; set; }
}
Step 3: Add a class file to the project. Name it EmployeeDBContext.cs. Copy and paste the following code.
using System.Data.Entity;
public class EmployeeDBContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.Map(m => m.Requires("IsTerminated")
.HasValue(false))
.Ignore(m => m.IsTerminated);

base.OnModelCreating(modelBuilder);
}
}
Step 4: Add the database connection string in web.config file.
<connectionStrings>
<add name="EmployeeDBContext"
connectionString="server=.; database=Sample; integrated security=SSPI;"
providerName="System.Data.SqlClient" />
</connectionStrings>

Step 5: Add a webform to the project. Drag and drop a GridView control.

Step 6: Copy and paste the following code in the code-behind file.
protected void Page_Load(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
GridView1.DataSource = employeeDBContext.Employees.ToList();
GridView1.DataBind();
}

27
Step 7: If you already have Sample database in SQL Server. Delete it from SQL Server Management Studio.

Step 8: Run the application. Sample database and Employees table must be created at this point.

Self-referencing association in entity framework Data base First:


This table is a self-referencing table because to get the manager of an employee, we
take ManagerIdcolumn value and look up in the EmployeeId column of the same table.

SQL script to create the table


Create table Employees
(
EmployeeID int primary key identity,
EmployeeName nvarchar(50),
ManagerID int foreign key references Employees(EmployeeID)
)
Now if you generate an ADO.NET entity data model based on this Employees table, the
following Employee entity is generated. Notice that a self-referencing association and 2 navigation
properties (Employees1 & Employee1) are automatically created.

Right click on Employees1 navigation property and select properties. In the properties window notice that
the Multiplicity is set to Many. So, this navigation property returns employees who are subordinates.

28
Similarly, right click on Employee1 navigation property and select properties. In the properties window
notice that the Multiplicity is set to Zero or One. So, this navigation property returns the manager of an
employee.

From a developer perspective the default navigation property names that entity framework generates are
not meaningful. If you have to write any code based on these navigation properties, it can get even more
complicated.

For example, let us say we want to display Employee names and their respective manager names as shown
below.

To achieve this we would drag and drop a GridView control on the web form and write the following code in
the code-behind file Page_Load event.
Now let's give these navigation properties meaningful names. To do this,
1. Right click on Employees1 navigation property and rename it to Subordinates
2. Similarly, right click on Employee1 navigation property and rename it to Manager

Now the code in the code-behind file would change as shown below which is more readable and
maintainable.

29
protected void Page_Load(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
GridView1.DataSource = employeeDBContext.Employees.Select(emp => new
{
EmployeeName = emp.EmployeeName,
ManagerName = emp.Manager == null ? "Super Boss"
: emp.Manager.EmployeeName
}).ToList();
GridView1.DataBind();
}
Self-referencing association in entity framework with code first:
self-referencing association in entity framework with code first approach.

Step 1: Create a new empty asp.net web application project. Name it Demo. Install entity framework if it's
not already installed.

Step 2: Add a class file to the project. Name it Employee.cs. Copy and paste the following code.
public class Employee
{
// Scalar properties
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
public int? ManagerID { get; set; }
// Navigation property
public Employee Manager { get; set; }
}
Step 3: Add a class file to the project. Name it EmployeeDBContext.cs. Copy and paste the following code.
using System.Data.Entity;
public class EmployeeDBContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.HasOptional(e => e.Manager)
.WithMany()
.HasForeignKey(m => m.ManagerID);
base.OnModelCreating(modelBuilder);
}
}

Step 4: Add the database connection string in web.config file.


<connectionStrings>
<add name="EmployeeDBContext"
connectionString="server=.; database=Sample; integrated security=SSPI;"
providerName="System.Data.SqlClient" />
</connectionStrings>

30
Step 5: Add a webform to the project. Drag and drop a GridView control.

Step 6: Copy and paste the following code in the code-behind file.
using System.Linq;
protected void Page_Load(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
GridView1.DataSource = employeeDBContext.Employees.Select(emp => new
{
EmployeeName = emp.EmployeeName,
ManagerName = emp.Manager == null ? "Super Boss" : emp.Manager.EmployeeName
}).ToList();
GridView1.DataBind();
}
Step 7: If you already have Sample database in SQL Server. Delete it from SQL Server Management Studio.
Step 8: Run the application. Sample database and Employees table must be created at this point. Notice
that EmployeeID is marked as primary key and ManagerID is marked as foreign key.

Table per Hierarchy (TPH) inheritance in entity framework Database


First:
implementing Table Per Hierarchy (TPH) inheritance in entity framework with database first approach. In
TPH inheritance one database table is used to store data for all of the entity types in the inheritance
hierarchy

We will be using the following Employees table.

SQL Script to create Employees Table


Create Table Employees
(
ID int primary key identity,
FirstName nvarchar(50),
LastName nvarchar(50),
Gender nvarchar(50),
AnuualSalary int,
HourlyPay int,
HoursWorked int,
Discriminator nvarchar(50)

31
)
In our organization we have 2 types of employees
1. Permanent Employees - AnuualSalary is specific for Permanent Employees
2. Contract Employees - HourlyPay & HoursWorked is specific for Contract Employees

Now if we generate an ADO.NET entity data model based on this Employees table, by default the following
Employee entity class is generated.

But from an application perspective we want 3 entity classes


Employee - This should be an abstract class and should contain all the common properties of permanent and
contract employees. ID, FirstName, LastName & Gender properties should be present in this class.

PermanentEmployee - This class should inherit from the abstract Employee class and should contain
AnnualSalary property

ContractEmployee - This class should inherit from the abstract Employee class and should contain HourlyPay
& HoursWorked properties

To achieve this using the Entity Framework designer


1. Right click on the designer surface and select Add - Entity option, and provide the details as shown below
and click OK.

2. Cut AnnualSalary property from Employee entity and paste it in Permanent Employee entity.

32
3. Right click on the designer surface and select Add - Entity option, and provide the details as shown below
and click OK.

4. Cut HourlyPay & HoursWorked properties from Employee entity and paste then inContract
Employee entity. At this point, we should have the following 3 entities.

5. Right click on PermanentEmployee and select Table Mapping option, and


mapPermanentEmployee entity to Employees table. Also notice the conditional mapping,in which we are
using Discriminator column to determine when an Employee can bePermanentEmployee.

33
6. Along the same lines, right click on ContractEmployee and select Table Mappingoption, and
map ContractEmployee entity to Employees table. Also notice theconditional mapping, in which we are
using Discriminator column to determine when an Employee can be ContractEmployee.

7. Since we are using Discriminator column in conditional mapping we cannot use it again with property
mapping in Employee entity. So delete it from there.

8. Finally right click on Employee entity and select properties. In the properties window set Abstract=true.
This should make Employee class an abstract class.

Now, let us see how to query the data. Design a webform as shown below.

Here is the HTML for the web form


<div style="font-family: Arial">
<asp:RadioButtonList ID="RadioButtonList1" runat="server" AutoPostBack="True"
OnSelectedIndexChanged="RadioButtonList1_SelectedIndexChanged">
<asp:ListItem Text="Load all Employees" Value="All"></asp:ListItem>
<asp:ListItem Text="Load Permanent Employees" Value="Permanent"></asp:ListItem>
<asp:ListItem Text="Load Contract Employees" Value="Contract"></asp:ListItem>
</asp:RadioButtonList>
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>

34
</div>

Here is the code behind code:


using System.Data;
using System.Linq;
protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
switch (RadioButtonList1.SelectedValue)
{
case "Permanent":
GridView1.DataSource=employeeDBContext.Employee.OfType<PermanentEmployee>().ToList();
GridView1.DataBind();
break;
case "Contract":
GridView1.DataSource = employeeDBContext.Employees.OfType<ContractEmployee>().ToList();
GridView1.DataBind();
break;

default:
GridView1.DataSource = ConvertEmployeesForDisplay(employeeDBContext.Employees.ToList());
GridView1.DataBind();
break;
}
}
private DataTable ConvertEmployeesForDisplay(List<Employee> employees)
{
DataTable dt = new DataTable();
dt.Columns.Add("ID"); dt.Columns.Add("FirstName");
dt.Columns.Add("LastName"); dt.Columns.Add("Gender");
dt.Columns.Add("AnuualSalary"); dt.Columns.Add("HourlyPay");
dt.Columns.Add("HoursWorked"); dt.Columns.Add("Type");
foreach (Employee employee in employees)
{
DataRow dr = dt.NewRow();
dr["ID"] = employee.ID; dr["FirstName"] = employee.FirstName;
dr["LastName"] = employee.LastName; dr["Gender"] = employee.Gender;
if (employee is PermanentEmployee)
{
dr["AnuualSalary"] = ((PermanentEmployee)employee).AnuualSalary;
dr["Type"] = "Permanent";
}
else
{
dr["HourlyPay"] = ((ContractEmployee)employee).HourlyPay;
dr["HoursWorked"] = ((ContractEmployee)employee).HoursWorked;
dr["Type"] = "Contract";
}

35
dt.Rows.Add(dr);
}
return dt;
}
Run the application and turn on the SQL profiler to inspect the queries that are generated.
Table Per Hierarchy (TPH) inheritance in entity framework with code
first:
In TPH inheritance one database table is used to store data for all of the entity types in the inheritance
hierarchy.
Step 1: Create a new empty asp.net web application project. Name it Demo. Install entity framework if it's
not already installed.

Step 2: Add a class file to the project. Name it Employee.cs. Copy and paste the following code.
using System.ComponentModel.DataAnnotations.Schema;
public abstract class Employee
{
[Column(Order = 1)]
public int ID { get; set; }
[Column(Order = 2)]
public string FirstName { get; set; }
[Column(Order = 3)]
public string LastName { get; set; }
[Column(Order = 4)]
public string Gender { get; set; }
}

Step 3: Add a class file to the project. Name it PermanentEmployee.cs. Copy and paste the following code.
using System.ComponentModel.DataAnnotations.Schema;
public class PermanentEmployee : Employee

36
{
[Column(Order = 5)]
public int AnnualSalary { get; set; }
}

Step 4: Add a class file to the project. Name it ContractEmployee.cs. Copy and paste the following code.
using System.ComponentModel.DataAnnotations.Schema;
public class ContractEmployee : Employee
{
[Column(Order = 6)]
public int HoursWorked { get; set; }
[Column(Order = 7)]
public int HourlyPay { get; set; }
}
Step 5: Add a class file to the project. Name it EmployeeDBContext.cs. Copy and paste the following code.
using System.Data.Entity;
public class EmployeeDBContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
}
Step 6: Add the database connection string in web.config file.
<connectionStrings>
<add name="EmployeeDBContext"
connectionString="server=.; database=Sample; integrated security=SSPI;"
providerName="System.Data.SqlClient" />
</connectionStrings>

Step 7:Repeat those above example


protected void btnAddPermanentEmployee_Click(object sender, EventArgs e)
{
PermanentEmployee permanentEmployee = new PermanentEmployee
{
FirstName = "Mike", LastName = "Brown",
Gender = "Male", AnnualSalary = 70000
};
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
employeeDBContext.Employees.Add(permanentEmployee);
employeeDBContext.SaveChanges();
}
protected void btnAddContractEmployee_Click(object sender, EventArgs e)
{
ContractEmployee contractEmployee = new ContractEmployee
{
FirstName = "Stacy",LastName = "Josh",
Gender = "Female", HourlyPay = 50,HoursWorked = 120
};
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
employeeDBContext.Employees.Add(contractEmployee);
employeeDBContext.SaveChanges();

37
}
Step 7: If you already have Sample database in SQL Server. Delete it from SQL Server Management Studio.

Step 8: Run the application. Sample database and Employees table must be created at this point.

Table per Type (TPT) inheritance in entity framework Database First:


In TPT inheritance one database table per type is used to store data for the respective entity types in the
inheritance hierarchy. This means there is no problem of de-normalized tables.

With TPH one database table is used to store data of all the entity types in the inheritance hierarchy. The
downside of this is that we have a denormalized table and some columns will have NULL values depending
on the type of the derived object being saved to the database table.

Example: Consider the following inheritance hierarchy

The data of all the entity types in the above inheritance hierarchy is stored in the following Employees table

The problem with TPH is that when we store a PermanentEmployee object to this table, HoursWorked &
HourlyPay columns will be left NULL. Along the same lines, when we store a ContractEmployee object,
AnnualSalary column will be NULL. With Table Per Type inheritance we don't have this problem.

We will be using the followin 3 tables to implement Table Per Type (TPT) inheritance. Notice
that EmployeeID is the primary key of Employees table. InPermanentEmployees & ContractEmployees,
EmployeeID is the foreign key.

38
SQL Script to create the 3 tables
Create Table Employees
(
EmployeeID int primary key,
FirstName nvarchar(50),
LastName nvarchar(50),
Gender nvarchar(50),
)
Create Table PermanentEmployees
(
EmployeeID int foreign key references
Employees(EmployeeID) not null,
AnnualSalary int
)
Create Table ContractEmployees
(
EmployeeID int foreign key references
Employees(EmployeeID) not null,
HourlyPay int,
HoursWorked int
)

Now if we generate an ADO.NET entity data model based on the above 3 tables, the following 3 entities are
generated with an association instead of inheritance relation between the entities.

Delete the association between Employee and PermanentEmployee entities. This will also automatically
delete the PermanentEmployee navigation property from Employeeentity and Employee navigation
property from PermanentEmployee entity.

39
Along the same lines, delete the association between Employee andContractEmployee entities. This will
also automatically delete the ContractEmployeenavigation property from Employee entity
and Employee navigation property fromContractEmployee entity.

Now, add the inheritance relationship between Employee & ContractEmployee entities
1. Right click on the designer surface and select Add - Inheritance option
2. Select Employee as the Base Entity and ContractEmployee as the Derived entity

Along the same line, add the inheritance relationship between Employee &PermanentEmployee entities
1. Right click on the designer surface and select Add - Inheritance option
2. Select Employee as the Base Entity and PermanentEmployee as the Derived entity

Now delete the EmployeeID property from both PermanentEmployee &ContractEmployee entities. For
both of these entities EmployeeID property will be available from the base Employee entity thru
inheritance.

At this point, the entity model should look as shown below.

40
Now, let us see how to query the data. Design a webform as shown below.

Here is the HTML for the web form: Refer the TPH Hierarchy Data base first approach
Run the application and turn on the SQL profiler to inspect the queries that are generated.

Table Per Type (TPT) inheritance in entity framework code first:


In TPT inheritance one database table per type is used to store data for the respective entity types in the
inheritance hierarchy.

Step 1: Create a new empty asp.net web application project. Name it Demo. Install entity framework if it's
not already installed.

Step 2: Add a class file to the project. Name it Employee.cs. Copy and paste the following code.
using System.ComponentModel.DataAnnotations.Schema;
[Table("Employees")]
public class Employee
{
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
}
Step 3: Add a class file to the project. Name it PermanentEmployee.cs. Copy and paste the following code.
using System.ComponentModel.DataAnnotations.Schema;
[Table("PermanentEmployees")]
public class PermanentEmployee : Employee

41
{
public int AnnualSalary { get; set; }
}
Step 4: Add a class file to the project. Name it ContractEmployee.cs. Copy and paste the following code.
using System.ComponentModel.DataAnnotations.Schema;
[Table("ContractEmployees")]
public class ContractEmployee : Employee
{
public int HoursWorked { get; set; }
public int HourlyPay { get; set; }
}
Step 5: Add a class file to the project. Name it EmployeeDBContext.cs. Copy and paste the following code.
using System.Data.Entity;
public class EmployeeDBContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
}
Step 6: Add the database connection string in web.config file.
<connectionStrings>
<add name="EmployeeDBContext"
connectionString="server=.; database=Sample; integrated security=SSPI;"
providerName="System.Data.SqlClient" />
</connectionStrings>

Step 7: Refer the TPH inheritance Code first approach


Step 8: Run the application. Sample database and the required tables (Employees, PermanentEmployees &
ContractEmployees) must be created at this point.

Step 10: Reload the webform. Open SQL Profiler. Select the different radio buttons to load contract,
permanent & all employees and notice the queries generated by the entity framework. Also click on the
following buttons.
a) Add Permanent Employee
b) Add Contract Employee

Notice that entity framework automatically inserts records into the correct underlying tables based on the
type of Employee (PermanentEmployee or ContractEmployee) being inserted.

Note: You can also use Fluent API to do the table mapping by overriding OnModelCreating() as shown below.
public class EmployeeDBContext : DbContext
{
public DbSet<Employee> Employees { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)


{
modelBuilder.Entity<ContractEmployee>().ToTable("ContractEmployees");
modelBuilder.Entity<PermanentEmployee>().ToTable("PermanentEmployees");

base.OnModelCreating(modelBuilder);
}
}

42
Many to many relationship in entity framework Database First:
We will be using the following 3 tables in this demo. There is aMany-to-Many relationship
between Courses and Students. A student can enroll into many courses and a single course can have many
students enrolled. The data is stored in the StudentCourses bridge table

SQL Script to create the above 3 tables


Create Table Courses
(
CourseID int identity primary key,
CourseName nvarchar(50)
)
Create Table Students
(
StudentID int identity primary key,
StudentName nvarchar(50)
)
Create Table StudentCourses
(
StudentID int not null foreign key references Students(StudentID),
CourseID int not null foreign key references Courses(CourseID)
primary key (StudentID, CourseID)
)

Now if we generate an ADO.NET entity data model based on the above 3 tables, only 2
entities (Student & Course) are generated with a Many-to-Many association between them. Notice that an
entity for the bridge table (StudentCourses) is not generated in the entity model. Also, notice that we have
navigation properties to navigate from Course to Students and from Student to Courses.

43
At this point, right click on Many-to-Many association and select Table Mapping option. In the Mapping
Details window notice that, the StudentCourses Many-to-Many association is mapped to StudentCourses
database table.

Now, let us see how to query the data. We want to display all the students names and the courses they have
opted into.

Drag and drop a GridView control on the webform. Copy and paste the following code in the code-behind
file.
protected void Page_Load(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();

GridView1.DataSource = from student in employeeDBContext.Students


from course in student.Courses
select new
{
StudentName = student.StudentName,
CourseName = course.CourseName
};
GridView1.DataBind();
}
Modifying data:
Assign Mike to WCF course
Remove John from SQL Server course
To achieve this,
1. Drag and Drop 2 button controls on the web form
2. Change text on the
First button to Assign WCF Course to Mike

44
Second button to Remove John from SQL Server Course
3. Copy and paste the following code in the respective click event handler methods
protected void Button1_Click(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
Course WCFCourse = employeeDBContext.Courses
.FirstOrDefault(x => x.CourseID == 4);

employeeDBContext.Students.FirstOrDefault(x => x.StudentID == 1)


.Courses.Add(WCFCourse);
employeeDBContext.SaveChanges();
}
protected void Button2_Click(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
Course SQLServerCourse = employeeDBContext.Courses
.FirstOrDefault(x => x.CourseID == 3);

employeeDBContext.Students.FirstOrDefault(x => x.StudentID == 2)


.Courses.Remove(SQLServerCourse);
employeeDBContext.SaveChanges();
}

Turn on SQL Profiler and load the webform. Click on the buttons and notice the queries generated.
Query to assign WCF course to Mike
exec sp_executesql N'insert [dbo].[StudentCourses]([StudentID], [CourseID])
values (@0, @1)',N'@0 int,@1 int',@0=1,@1=4

Query to remove John from SQL Server Course


exec sp_executesql N'delete [dbo].[StudentCourses] where
(([StudentID] = @0) and ([CourseID] = @1))',N'@0 int,@1 int',@0=2,@1=3

Many to many relationship in entity framework code first:


Based on Course & Student classes, entity framework should generate the required database tables
with many-to-many relationship

Step 1: Create a new empty asp.net web application project. Name it Demo. Install entity framework if it's
not already installed.

Step 2: Add a class file to the project. Name it Course.cs. Copy and paste the following code.
using System.Collections.Generic;
public class Course
{
public int CourseID { get; set; }
public string CourseName { get; set; }
public IList<Student> Students { get; set; }
}
Step 3: Add a class file to the project. Name it Student.cs. Copy and paste the following code.

45
using System.Collections.Generic;
public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public IList<Course> Courses { get; set; }
}
Step 4: Add a class file to the project. Name it EmployeeDBContext.cs. Copy and paste the following code.
using System.Data.Entity;
public class EmployeeDBContext : DbContext
{
public DbSet<Course> Courses { get; set; }
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>()
.HasMany(t => t.Courses)
.WithMany(t => t.Students)
.Map(m =>
{
m.ToTable("StudentCourses");
m.MapLeftKey("StudentID");
m.MapRightKey("CourseID");
});
base.OnModelCreating(modelBuilder);
}
}
Step 5: Add the database connection string in web.config file.
<connectionStrings>
<add name="EmployeeDBContext"
connectionString="server=.; database=Sample; integrated security=SSPI;"
providerName="System.Data.SqlClient" />
</connectionStrings>

Step 6: Add a webform to the project. Copy and paste the following HTML.
Same as above example

Step 7: Copy and paste the following code in the code-behind file.
using System.Linq;
protected void Page_Load(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();

GridView1.DataSource = (from student in employeeDBContext.Students


from c in student.Courses
select new
{
StudentName = student.StudentName,
CourseName = c.CourseName

46
}).ToList();
GridView1.DataBind();
}
protected void Button1_Click(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
Course WCFCourse = employeeDBContext.Courses.FirstOrDefault(x => x.CourseID == 4);
employeeDBContext.Students.Include("Courses")
.FirstOrDefault(x => x.StudentID == 1).Courses.Add(WCFCourse);
employeeDBContext.SaveChanges();
}
protected void Button2_Click(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
Course SQLServerCourse = employeeDBContext.Courses.FirstOrDefault(x => x.CourseID == 3);
employeeDBContext.Students.Include("Courses")
.FirstOrDefault(x => x.StudentID == 2).Courses.Remove(SQLServerCourse);
employeeDBContext.SaveChanges();
}

Step 8: If you already have Sample database in SQL Server. Delete it from SQL Server Management Studio.

Step 9: Run the application. Sample database and the required tables (Courses, Students & StudentCourses)
must be created at this point.

Step 11: Reload the webform. Notice that the data is displayed as expected. Now, click on the following
buttons, and notice that StudentCourses table is updated as expected.
a) Assign WCF Course to Mike
b) Remove John from SQL Server Course

Entity for BridgeTable in many to many relationship data base first:


Notice that the Bridge Table (StudentCourses) does not have any additional columns except for the foreign
keys (StudentID & CourseID). When an entity model was created based on these 3 tables, an entity for the
bridge table is not created.

Let us now, modify the Bridge Table (StudentCourses) to include EnrolledDate column.

SQL Script to create all the 3 tables (Courses, Students & StudentCourses)
Create Table Courses
(
CourseID int identity primary key,
CourseName nvarchar(50)
)
Create Table Students
(
StudentID int identity primary key,
StudentName nvarchar(50)
)
Create Table StudentCourses
(

47
StudentID int not null foreign key references Students(StudentID),
CourseID int not null foreign key references Courses(CourseID),
EnrolledDate DateTime,
primary key (StudentID, CourseID)
)

Now if we generate an ADO.NET entity data model based on the above 3 tables, notice that 3 entities
(Student, Course & StudentCourse) are generated. An entity (StudentCourse) for the bridge table
(StudentCourses) is also generated.
a) Student entity has One-Many relationship with StudentCourse Entity
b) Course entity has One-Many relationship with StudentCourse Entity

Entity Framework interview question : Explain when an entity will and will not be created by the entity
framework for the bridge table in a many-to-many relationship?
An entity for the bridge table is NOT created when the bridge table has only the foreign keys. On the other if
the bridge table has any other columns apart from the foreign key columns then a bridge table is created.

Querying data: We want to display students and courses data in a GridView as shown below.

To achieve this
1. Drag and drop a GridView & 2 Button controls on the webform

2. Change the Text on Button1 control to "Assign WCF Course to Mike" and double click on the button
control to generate the click event handler

3. Change the Text on Button2 control to "Remove John from SQL Server Course"and double click on the
button control to generate the click event handler

4. At this point the webform design should look Same as above example

Copy and paste the following code in the code-behind file


using System;
using System.Linq;
protected void Page_Load(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
GridView1.DataSource = (from student in employeeDBContext.Students
from studentCourse in student.StudentCourses
select new
{
StudentName = student.StudentName,
CourseName = studentCourse.Course.CourseName,
EnrolledDate = studentCourse.EnrolledDate
}).ToList();

48
// The above query can also be written as shown below
//GridView1.DataSource = (from course in employeeDBContext.Courses
// from studentCourse in course.StudentCourses
// select new
// {
// StudentName = studentCourse.Student.StudentName,
// CourseName = course.CourseName,
// EnrolledDate = studentCourse.EnrolledDate
// }).ToList();

GridView1.DataBind();
}
protected void Button1_Click(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
employeeDBContext.StudentCourses.AddObject
(new StudentCourse { StudentID = 1, CourseID = 4,
EnrolledDate = DateTime.Now });
employeeDBContext.SaveChanges();
}
protected void Button2_Click(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
StudentCourse studentCourseToRemove = employeeDBContext.StudentCourses
.FirstOrDefault(x => x.StudentID == 2 && x.CourseID == 3);
employeeDBContext.StudentCourses.DeleteObject(studentCourseToRemove);
employeeDBContext.SaveChanges();
}
Run the application. Notice that the data is displayed as expected. Now, click on the following buttons, and
notice that StudentCourses table is updated as expected.
a) Assign WCF Course to Mike
b) Remove John from SQL Server Course

Entity for BridgeTable in many to many relationship code first:


1. Courses - CourseID should be the Primary Key
2. Students - StudentID should be the Primary Key
3. StudentCourses - Composite primary key consisting of CourseID & StudentIDcolumns. CourseID should
also be the foreign key referencing CourseID column in Courses table. StudentID should also be the foreign
key referencing StudentID column in Students table.

To achieve this
Step 1: Create a new empty asp.net web application project. Name it Demo. Install entity framework if it's
not already installed.

Step 2: Add a class file to the project. Name it Course.cs. Copy and paste the following code.
using System.Collections.Generic;
public class Course
{
public int CourseID { get; set; }

49
public string CourseName { get; set; }
public IList<StudentCourse> StudentCourses { get; set; }
}
Step 3: Add a class file to the project. Name it Student.cs. Copy and paste the following code.
using System.Collections.Generic;
public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public IList<StudentCourse> StudentCourses { get; set; }
}
Step 4: Add a class file to the project. Name it StudentCourse.cs. Copy and paste the following code.
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class StudentCourse
{
public Course Course { get; set; }
public Student Student { get; set; }
[Key, Column(Order = 1)]
public int StudentID { get; set; }
[Key, Column(Order = 2)]
public int CourseID { get; set; }
public DateTime EnrolledDate { get; set; }
}
Step 5: Add a class file to the project. Name it EmployeeDBContext.cs. Copy and paste the following code.
using System.Data.Entity;
public class EmployeeDBContext : DbContext
{
public DbSet<Course> Courses { get; set; }
public DbSet<Student> Students { get; set; }
public DbSet<StudentCourse> StudentCourses { get; set; }
}
Step 6: Add the database connection string in web.config file.
<connectionStrings>
<add name="EmployeeDBContext"
connectionString="server=.; database=Sample; integrated security=SSPI;"
providerName="System.Data.SqlClient" />
</connectionStrings>

Step 7: Add a webform to the project. Copy and paste the following HTML.
Same as above example

Step 8: Copy and paste the following code in the code-behind file.
using System.Linq;
protected void Page_Load(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();

50
GridView1.DataSource = (from student in employeeDBContext.Students
from studentCourse in student.StudentCourses
select new
{
StudentName = student.StudentName,
CourseName = studentCourse.Course.CourseName,
EnrolledDate = studentCourse.EnrolledDate
}).ToList();

// The above query can also be written as shown below


//GridView1.DataSource = (from course in employeeDBContext.Courses
// from studentCourse in course.StudentCourses
// select new
// {
// StudentName = studentCourse.Student.StudentName,
// CourseName = course.CourseName,
// EnrolledDate = studentCourse.EnrolledDate
// }).ToList();

GridView1.DataBind();
}
protected void Button1_Click(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
employeeDBContext.StudentCourses.Add(new StudentCourse
{ StudentID = 1, CourseID = 4, EnrolledDate = DateTime.Now });
employeeDBContext.SaveChanges();
}
protected void Button2_Click(object sender, EventArgs e)
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
StudentCourse studentCourseToRemove = employeeDBContext.StudentCourses
.FirstOrDefault(x => x.StudentID == 2 && x.CourseID == 3);
employeeDBContext.StudentCourses.Remove(studentCourseToRemove);
employeeDBContext.SaveChanges();
}

Step 9: If you already have Sample database in SQL Server. Delete it from SQL Server Management Studio.

Step 10: Run the application. Sample database and the required tables (Courses, Students &
StudentCourses) must be created at this point.

Step 11: Reload the webform. Notice that the data is displayed as expected. Now, click on the following
buttons, and notice that StudentCourses table is updated as expected.
a) Assign WCF Course to Mike
b) Remove John from SQL Server Course

51

Вам также может понравиться