0% found this document useful (0 votes)
9 views39 pages

Unit 3

Entity Framework is an open-source object-relational mapper for .NET applications that enhances developer productivity by allowing interaction with data through domain-specific objects rather than database tables. It simplifies database operations, supports various features like change tracking and transaction management, and provides a high-level API for working with relational data. The document also discusses the advantages and disadvantages of ORM frameworks, and highlights popular ORM options in the .NET ecosystem, including Entity Framework Core, NHibernate, and Dapper.

Uploaded by

karthicsonia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views39 pages

Unit 3

Entity Framework is an open-source object-relational mapper for .NET applications that enhances developer productivity by allowing interaction with data through domain-specific objects rather than database tables. It simplifies database operations, supports various features like change tracking and transaction management, and provides a high-level API for working with relational data. The document also discusses the advantages and disadvantages of ORM frameworks, and highlights popular ORM options in the .NET ecosystem, including Entity Framework Core, NHibernate, and Dapper.

Uploaded by

karthicsonia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 39

UNIT-III

What is Entity Framework ?


Entity Framework is an open-source object-relational mapper framework for .NET applications
supported by Microsoft. It increases the developer’s productivity as it enables developers to work
with data using objects of domain-specific classes without focusing on the underlying database
tables and columns where this data is stored. It eliminates the need for most of the data-access
code which is used to interact with the database that developers usually need to write. It provides
an abstract level to the developers to work with a relational table and columns by using the
domain-specific object. It also reduces the code size of the data specific applications and also the
readability of the code increases by using it. This is a new technology for accessing the data for
Microsoft application. The latest version for Entity Framework is 6.0.
The following figure describes where the Entity Framework present in your application.

The above figure represents how an entity framework interacts with the domain class and
database. It provides a connection between the business entity and data tables in the database. It
saves data stored in the properties of business entities and also retrieves data from the database
and converts it to business entities objects automatically. Entity Framework will execute the
relevant query in the database and then materialize results into instances of your domain objects
for you to work within your app.
What is Entity Framework?
Entity Framework was first released in 2008, Microsoft's primary means of interacting
between .NET applications and relational databases. Entity Framework is an Object Relational
Mapper (ORM) which is a type of tool that simplifies mapping between objects in your software
to the tables and columns of a relational database.
 Entity Framework (EF) is an open source ORM framework for ADO.NET which is a part
of .NET Framework.
 An ORM takes care of creating database connections and executing commands, as well as
taking query results and automatically materializing those results as your application
objects.
 An ORM also helps to keep track of changes to those objects, and when instructed, it will
also persist those changes back to the database for you.
Conceptual Model

When defining the class and features of entity framework first and then entity framework convert
it into the conceptual model first and it creates database and objects in the database from the
conceptual model this method is called Code First. Now your object directly works with the
database to retrieve or make changes.
Features of Entity Framework
 It is platform independent.
 It uses LinQ queries to manipulate the data in the database instead of SQL queries.
 It keep the track of values that have been changed of the properties of entities.
 It also save changes which are done insert, delete or update operations.
 It also handle concurrency so the data override by a user and will reflect when another use
fetches it.
 It also handles transaction management automatically and also provides the customize options
for transaction management.
 It provides caching which means it stores the result of the frequently used queries.
 It also follow certain conventions for programming so it by default configure the EF Model.
 It also allows to configure the EF Model by a fluent API to override the default convention.
 If you made any changes in database schema then you can reflect those changes in EF model
by writing migration command in CLI(Command Line Interface).
 It also support stored procedure.
 It also support parameterized queries.
ORM
What is an ORM?
ORM stands for Object-Relational Mapping. It is a programming technique used to map data
between an object-oriented programming language and a relational database management system
(RDBMS).
The goal of ORM is to simplify the development of data-driven applications by providing a high-
level, object-oriented API that can be used to interact with the database. ORM frameworks provide
a set of classes and methods that map database tables and relationships to objects and collections of
objects in the programming language.

ORM sets the mapping between the set of objects which are written in the preferred programming
language like JavaScript and relational database like SQL. It hides and encapsulates the SQL
queries into objects and instead of SQL queries we can use directly the objects to implement the
SQL query.
In an ORM framework, a database table is represented by a class, and each row in the table is
represented by an instance of the class. The ORM framework handles the mapping of data between
the class instances and the database tables. This means that developers can work with objects in
their programming language of choice, rather than writing SQL queries and working with result
sets.
ORM frameworks also provide features such as caching, lazy loading, and change tracking, which
can improve performance and simplify application development.
Some popular ORM frameworks include Entity Framework Core, Hibernate (for Java), and Django
ORM (for Python).
ORM (Object-Relational Mapping) is required for several reasons:
 Object-Oriented Programming: Most modern programming languages, such as C#, Java,
Python, and Ruby, are object-oriented. ORM frameworks allow developers to work with
objects in their programming language of choice, which simplifies application
development.
 Database Abstraction: ORM frameworks abstract the details of the underlying database,
including table structures, relationships, and data types. This means that developers can
work with a higher-level API instead of writing SQL queries and managing result sets.
 Security: ORM frameworks can provide security features such as parameterized queries
and data validation, which can help prevent SQL injection attacks and other security
vulnerabilities.
 Performance: ORM frameworks can improve performance by caching data, reducing the
number of database queries required, and optimizing database access.
 Maintenance: ORM frameworks can simplify maintenance by allowing developers to
work with a single set of object-oriented classes that map to database tables, rather than
having to manage both object-oriented classes and SQL queries separately.
 In summary, ORM frameworks provide a higher-level, object-oriented API that simplifies
database access, improves security, and can improve application performance and
maintenance.
 While ORM (Object-Relational Mapping) can provide many benefits, there are also
some potential drawbacks to consider:
 Learning Curve: ORM frameworks can have a steep learning curve, especially for
developers who are not familiar with the specific framework. Developers need to
understand the framework’s conventions and configuration options to use it effectively.
 Performance Overhead: ORM frameworks can introduce additional performance
overhead compared to direct SQL queries. The ORM framework must translate object-
oriented operations into SQL statements, which can add additional overhead and potentially
impact performance.
 Limited Control: ORM frameworks can limit the control that developers have over the
SQL statements that are executed against the database. This can limit the ability to optimize
queries for performance or to take advantage of database-specific features.
 Complexity: ORM frameworks can add complexity to the application, especially if the
database schema is complex or if the application uses advanced database features. In some
cases, it may be simpler and more efficient to write custom SQL queries instead of using an
ORM framework.
 Compatibility: ORM frameworks may not be compatible with all databases or database
features. Developers may need to use a different ORM framework or write custom SQL
queries to work with specific databases or features.
 In summary, while ORM frameworks can provide many benefits, they may also have some
drawbacks related to learning curve, performance overhead, limited control, complexity,
and compatibility. It is important to carefully evaluate these factors when deciding whether
to use an ORM framework in an application.
 Popular ORM In DOT NET
 There are several popular ORM (Object-Relational Mapping) frameworks in the .NET
ecosystem, including:
 Entity Framework Core: This is the most popular ORM framework for .NET and is
included in the .NET Core and .NET Framework runtime. It provides a high-level, object-
oriented API for working with databases and supports multiple database providers,
including SQL Server, MySQL, and PostgreSQL.
 NHibernate: This is a mature and popular ORM framework that has been around since
2005. It is based on the Java Hibernate framework and provides similar features for .NET
developers. NHibernate supports multiple database providers and is highly customizable.
 Dapper: This is a lightweight ORM framework that provides high performance and
supports raw SQL queries as well as object mapping. It is popular for applications that
require high performance and control over the SQL queries that are executed.
 In summary, the most popular ORM framework in the .NET ecosystem is Entity
Framework Core, followed by NHibernate, Dapper. Each of these frameworks has its own
strengths and weaknesses, and the choice of framework will depend on the specific
requirements of the application.
 When to use EF Core and Dapper
 EF Core and Dapper are both popular ORM (Object-Relational Mapping) frameworks in
the .NET ecosystem, but they have different strengths and weaknesses, and the choice of
framework will depend on the specific requirements of the application.
 EF Core is a full-featured ORM framework that provides a high-level, object-oriented API
for working with databases. It supports multiple database providers, including SQL Server,
MySQL, PostgreSQL, and SQLite, and provides features such as change tracking, lazy
loading, and automatic database schema migration. EF Core is ideal for applications that
require a high-level, object-oriented API and need to work with a variety of database
providers.
 Dapper, on the other hand, is a lightweight ORM framework that provides high
performance and supports raw SQL queries as well as object mapping. It is popular for
applications that require high performance and control over the SQL queries that are
executed. Dapper does not provide features such as change tracking or automatic schema
migration, so it is best suited for applications that require low-level control over database
access.
 In general, if an application requires a high-level, object-oriented API and needs to work
with a variety of database providers, EF Core is a good choice. If an application requires
high performance and low-level control over database access, Dapper is a good choice. It is
also possible to use both EF Core and Dapper in the same application, depending on the
specific requirements of different parts of the application.

TABLE MAPPING
1. Table splitting
2. Entity splitting
3. Table-specific facet configuration

EF Core offers a lot of flexibility when it comes to mapping entity types to tables in a database.
This becomes even more useful when you need to use a database that wasn't created by EF.
The below techniques are described in terms of tables, but the same result can be achieved when
mapping to views as well.
TABLE SPLITTING
EF Core allows to map two or more entities to a single row. This is called table splitting or table
sharing.
Configuration
To use table splitting the entity types need to be mapped to the same table, have the primary keys
mapped to the same columns and at least one relationship configured between the primary key of
one entity type and another in the same table.
A common scenario for table splitting is using only a subset of the columns in the table for greater
performance or encapsulation.
In this example Order represents a subset of DetailedOrder.
public class Order
{
public int Id { get; set; }
public OrderStatus? Status { get; set; }
public DetailedOrder DetailedOrder { get; set; }
}
public class DetailedOrder
{
public int Id { get; set; }
public OrderStatus? Status { get; set; }
public string BillingAddress { get; set; }
public string ShippingAddress { get; set; }
public byte[] Version { get; set; }
}
In addition to the required configuration we call Property(o =>
o.Status).HasColumnName("Status") to map DetailedOrder.Status to the same column
as Order.Status.
C#Copy
modelBuilder.Entity<DetailedOrder>(
dob =>
{
dob.ToTable("Orders");
dob.Property(o => o.Status).HasColumnName("Status");
});

modelBuilder.Entity<Order>(
ob =>
{
ob.ToTable("Orders");
ob.Property(o => o.Status).HasColumnName("Status");
ob.HasOne(o => o.DetailedOrder).WithOne()
.HasForeignKey<DetailedOrder>(o => o.Id);
ob.Navigation(o => o.DetailedOrder).IsRequired();
});

using (var context = new TableSplittingContext())


{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();

context.Add(
new Order
{
Status = OrderStatus.Pending,
DetailedOrder = new DetailedOrder
{
Status = OrderStatus.Pending,
ShippingAddress = "221 B Baker St, London",
BillingAddress = "11 Wall Street, New York"
}
});

context.SaveChanges();
}

using (var context = new TableSplittingContext())


{
var pendingCount = context.Orders.Count(o => o.Status == OrderStatus.Pending);
Console.WriteLine($"Current number of pending orders: {pendingCount}");
}
using (var context = new TableSplittingContext())
{
var order = context.DetailedOrders.First(o => o.Status == OrderStatus.Pending);
Console.WriteLine($"First pending order will ship to: {order.ShippingAddress}");
}
Optional dependent entity
If all of the columns used by a dependent entity are NULL in the database, then no instance for it
will be created when queried. This allows modeling an optional dependent entity, where the
relationship property on the principal would be null. Note that this would also happen if all of the
dependent's properties are optional and set to null, which might not be expected.
However, the additional check can impact query performance. In addition, if the dependent entity
type has dependents of its own, then determining whether an instance should be created becomes
non-trivial. To avoid these issues the dependent entity type can be marked as required,
see Required one-to-one dependents for more information.
Concurrency tokens
If any of the entity types sharing a table has a concurrency token then it must be included in all
other entity types as well. This is necessary in order to avoid a stale concurrency token value
when only one of the entities mapped to the same table is updated.
To avoid exposing the concurrency token to the consuming code, it's possible the create one as
a shadow property:
modelBuilder.Entity<Order>()
.Property<byte[]>("Version").IsRowVersion().HasColumnName("Version");

modelBuilder.Entity<DetailedOrder>()
.Property(o => o.Version).IsRowVersion().HasColumnName("Version");
Inheritance
It's recommended to read the dedicated page on inheritance before continuing with this section.
The dependent types using table splitting can have an inheritance hierarchy, but there are some
limitations:
 The dependent entity type cannot use TPC mapping as the derived types wouldn't be able to
map to the same table.
 The dependent entity type can use TPT mapping, but only the root entity type can use table
splitting.
 If the principal entity type uses TPC, then only the entity types that don't have any
descendants can use table splitting. Otherwise the dependent columns would need to be
duplicated on the tables corresponding to the derived types, complicating all interactions.
ENTITY SPLITTING
EF Core allows to map an entity to rows in two or more tables. This is called entity splitting.
Configuration
For example, consider a database with three tables that hold customer data:
 A Customers table for customer information
 A PhoneNumbers table for the customer's phone number
 An Addresses table for the customer's address
Here are definitions for these tables in SQL Server:
SQLCopy
CREATE TABLE [Customers] (
[Id] int NOT NULL IDENTITY,
[Name] nvarchar(max) NOT NULL,
CONSTRAINT [PK_Customers] PRIMARY KEY ([Id]));

CREATE TABLE [PhoneNumbers] (


[CustomerId] int NOT NULL,
[PhoneNumber] nvarchar(max) NULL,
CONSTRAINT [PK_PhoneNumbers] PRIMARY KEY ([CustomerId]),
CONSTRAINT [FK_PhoneNumbers_Customers_CustomerId] FOREIGN KEY ([CustomerId])
REFERENCES [Customers] ([Id]) ON DELETE CASCADE);

CREATE TABLE [Addresses] ( [CustomerId] int NOT NULL,


[Street] nvarchar(max) NOT NULL, [City] nvarchar(max) NOT NULL,
[PostCode] nvarchar(max) NULL, [Country] nvarchar(max) NOT NULL,
CONSTRAINT [PK_Addresses] PRIMARY KEY ([CustomerId]),
CONSTRAINT [FK_Addresses_Customers_CustomerId] FOREIGN KEY ([CustomerId])
REFERENCES [Customers] ([Id]) ON DELETE CASCADE);
Each of these tables would typically be mapped to their own entity type, with relationships
between the types. However, if all three tables are always used together, then it can be more
convenient to map them all to a single entity type. For example:

public class Customer


{
public Customer(string name, string street, string city, string? postCode, string country)
{
Name = name;
Street = street;
City = city;
PostCode = postCode;
Country = country;
}
public int Id { get; set; }
public string Name { get; set; }
public string? PhoneNumber { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string? PostCode { get; set; }
public string Country { get; set; }
}
This is achieved in EF7 by calling SplitToTable for each split in the entity type. For example, the
following code splits the Customer entity type to the Customers, PhoneNumbers,
and Addresses tables shown above:
modelBuilder.Entity<Customer>(
entityBuilder =>
{
entityBuilder
.ToTable("Customers")
.SplitToTable(
"PhoneNumbers",
tableBuilder =>
{
tableBuilder.Property(customer => customer.Id).HasColumnName("CustomerId");
tableBuilder.Property(customer => customer.PhoneNumber);
})
.SplitToTable(
"Addresses",
tableBuilder =>
{
tableBuilder.Property(customer => customer.Id).HasColumnName("CustomerId");
tableBuilder.Property(customer => customer.Street);
tableBuilder.Property(customer => customer.City);
tableBuilder.Property(customer => customer.PostCode);
tableBuilder.Property(customer => customer.Country);
});
});
Notice also that, if necessary, different column names can be specified for each of the tables. To
configure the column name for the main table see Table-specific facet configuration.
Configuring the linking foreign key
The FK linking the mapped tables is targeting the same properties on which it is declared.
Normally it wouldn't be created in the database, as it would be redundant. But there's an exception
for when the entity type is mapped to more than one table. To change its facets you can use
the relationship configuration Fluent API:
modelBuilder.Entity<Customer>()
.HasOne<Customer>()
.WithOne()
.HasForeignKey<Customer>(a => a.Id)
.OnDelete(DeleteBehavior.Restrict);
Limitations
 Entity splitting can't be used for entity types in hierarchies.
 For any row in the main table there must be a row in each of the split tables (the fragments
are not optional).
Table-specific facet configuration
Some mapping patterns result in the same CLR property being mapped to a column in each of
multiple different tables. EF7 allows these columns to have different names. For example,
consider a simple inheritance hierarchy:
C#Copy
public abstract class Animal
{
public int Id { get; set; }
public string Breed { get; set; } = null!;
}

public class Cat : Animal


{
public string? EducationalLevel { get; set; }
}

public class Dog : Animal


{
public string? FavoriteToy { get; set; }
}
With the TPT inheritance mapping strategy, these types will be mapped to three tables. However,
the primary key column in each table may have a different name. For example:
SQLCopy
CREATE TABLE [Animals] (
[Id] int NOT NULL IDENTITY,
[Breed] nvarchar(max) NOT NULL,
CONSTRAINT [PK_Animals] PRIMARY KEY ([Id])
);

CREATE TABLE [Cats] (


[CatId] int NOT NULL,
[EducationalLevel] nvarchar(max) NULL,
CONSTRAINT [PK_Cats] PRIMARY KEY ([CatId]),
CONSTRAINT [FK_Cats_Animals_CatId] FOREIGN KEY ([CatId]) REFERENCES
[Animals] ([Id]) ON DELETE CASCADE
);

CREATE TABLE [Dogs] (


[DogId] int NOT NULL,
[FavoriteToy] nvarchar(max) NULL,
CONSTRAINT [PK_Dogs] PRIMARY KEY ([DogId]),
CONSTRAINT [FK_Dogs_Animals_DogId] FOREIGN KEY ([DogId]) REFERENCES
[Animals] ([Id]) ON DELETE CASCADE
);
EF7 allows this mapping to be configured using a nested table builder:
C#Copy
modelBuilder.Entity<Animal>().ToTable("Animals");

modelBuilder.Entity<Cat>()
.ToTable(
"Cats",
tableBuilder => tableBuilder.Property(cat => cat.Id).HasColumnName("CatId"));

modelBuilder.Entity<Dog>()
.ToTable(
"Dogs",
tableBuilder => tableBuilder.Property(dog => dog.Id).HasColumnName("DogId"));
With the TPC inheritance mapping, the Breed property can also be mapped to different column
names in different tables. For example, consider the following TPC tables:
SQLCopy
CREATE TABLE [Cats] (
[CatId] int NOT NULL DEFAULT (NEXT VALUE FOR [AnimalSequence]),
[CatBreed] nvarchar(max) NOT NULL,
[EducationalLevel] nvarchar(max) NULL,
CONSTRAINT [PK_Cats] PRIMARY KEY ([CatId]));

CREATE TABLE [Dogs] (


[DogId] int NOT NULL DEFAULT (NEXT VALUE FOR [AnimalSequence]),
[DogBreed] nvarchar(max) NOT NULL,
[FavoriteToy] nvarchar(max) NULL,
CONSTRAINT [PK_Dogs] PRIMARY KEY ([DogId]));
EF7 supports this table mapping:
C#Copy
modelBuilder.Entity<Animal>().UseTpcMappingStrategy();

modelBuilder.Entity<Cat>()
.ToTable("Cats",builder => { builder.Property(cat => cat.Id).HasColumnName("CatId");
builder.Property(cat => cat.Breed).HasColumnName("CatBreed");
});

modelBuilder.Entity<Dog>()
.ToTable("Dogs",builder => {builder.Property(dog => dog.Id).HasColumnName("DogId");
builder.Property(dog => dog.Breed).HasColumnName("DogBreed");
});

ENTITY FRAMEWORK - DATABASE FIRST APPROACH


creating an entity data model with Database First approach.
 The Database First Approach provides an alternative to the Code First and Model First
approaches to the Entity Data Model. It creates model codes (classes, properties,
DbContext etc.) from the database in the project and those classes become the link
between the database and controller.
 The Database First Approach creates the entity framework from an existing database. We
use all other functionalities, such as the model/database sync and the code generation, in
the same way we used them in the Model First approach.
Let’s take a simple example. We already have a database which contains 3 tables as shown in the
following image.
Step 1 − Let’s create a new console project with DatabaseFirstDemo name.
Step 2 − To create the model, first right-click on your console project in solution explorer and
select Add → New Items…

Step 3 − Select ADO.NET Entity Data Model from middle pane and enter name
DatabaseFirstModel in the Name field.
Step 4 − Click Add button which will launch the Entity Data Model Wizard dialog.
Step 5 − Select EF Designer from database and click Next button.

Step 6 − Select the existing database and click Next.


Step 7 − Choose Entity Framework 6.x and click Next.

Step 8 − Select all the tables Views and stored procedure you want to include and click Finish.
You will see that Entity model and POCO classes are generated from the database.
Let us now retrieve all the students from the database by writing the following code in program.cs
file.
using System;
using System.Linq;
namespace DatabaseFirstDemo {
class Program {
static void Main(string[] args) {
using (var db = new UniContextEntities()) {
var query = from b in db.Students
orderby b.FirstMidName select b;
Console.WriteLine("All All student in the database:");
foreach (var item in query) {
Console.WriteLine(item.FirstMidName +" "+ item.LastName);
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}
}
When the above program is executed, you will receive the following output −
All student in the database:
Ali Khan
Arturo finand
Bill Gates
Carson Alexander
Gytis Barzdukas
Laura Norman
Meredith Alonso
Nino Olivetto
Peggy Justice
Yan Li
Press any key to exit...
When the above program is executed, you will see all the students’ name which were previously
entered in the database.
ENTITY FRAMEWORK - CODE FIRST APPROACH
The Entity Framework provides three approaches to create an entity model and each one has their
own pros and cons. *Code First * Database First * Model First
Some developers prefer to work with the Designer in Code while others would rather just work
with their code. For those developers, Entity Framework has a modeling workflow referred to as
Code First.
 Code First modeling workflow targets a database that doesn’t exist and Code First will
create it.
 It can also be used if you have an empty database and then Code First will add new tables
too.
 Code First allows you to define your model using C# or VB.Net classes.
 Additional configuration can optionally be performed using attributes on your classes and
properties or by using a fluent API.

Why Code First?


 Code First is really made up of a set of puzzle pieces. First are your domain classes.
 The domain classes have nothing to do with Entity Framework. They're just the items of
your business domain.
 Entity Framework, then, has a context that manages the interaction between those classes
and your database.
 The context is not specific to Code First. It's an Entity Framework feature.
 Code First adds a model builder that inspects your classes that the context is managing,
and then uses a set of rules or conventions to determine how those classes and the
relationships describe a model, and how that model should map to your database.
 All of this happens at runtime. You'll never see this model, it's just in memory.
 Code First has the ability to use that model to create a database if required.
 It can also update the database if the model changes, using a feature called Code First
Migrations.
Print Page
CODE FIRST CONVENTIONS
1. Type Discovery
2. Primary Key Convention
3. Relationship Convention
4. Complex Types Convention
Show 3 more
Code First enables you to describe a model by using C# or Visual Basic .NET classes. The basic
shape of the model is detected by using conventions. Conventions are sets of rules that are used to
automatically configure a conceptual model based on class definitions when working with Code
First. The conventions are defined in the System.Data.Entity.ModelConfiguration.Conventions
namespace.
You can further configure your model by using data annotations or the fluent API. Precedence is
given to configuration through the fluent API followed by data annotations and then conventions.
For more information see Data Annotations, Fluent API - Relationships, Fluent API - Types &
Properties and Fluent API with VB.NET.
A detailed list of Code First conventions is available in the API Documentation. This topic
provides an overview of the conventions used by Code First.
Type Discovery
When using Code First development you usually begin by writing .NET Framework classes that
define your conceptual (domain) model. In addition to defining the classes, you also need to
let DbContext know which types you want to include in the model. To do this, you define a
context class that derives from DbContext and exposes DbSet properties for the types that you
want to be part of the model. Code First will include these types and also will pull in any
referenced types, even if the referenced types are defined in a different assembly.
If your types participate in an inheritance hierarchy, it is enough to define a DbSet property for
the base class, and the derived types will be automatically included, if they are in the same
assembly as the base class.
In the following example, there is only one DbSet property defined on the SchoolEntities class
(Departments). Code First uses this property to discover and pull in any referenced types.
C#Copy
public class SchoolEntities : DbContext
{
public DbSet<Department> Departments { get; set; }
}
public class Department
{
// Primary key
public int DepartmentID { get; set; }
public string Name { get; set; }
// Navigation property
public virtual ICollection<Course> Courses { get; set; }
}
public class Course
{
// Primary key
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }
// Foreign key
public int DepartmentID { get; set; }
// Navigation properties
public virtual Department Department { get; set; }
}
public partial class OnlineCourse : Course
{
public string URL { get; set; }
}
public partial class OnsiteCourse : Course
{
public string Location { get; set; }
public string Days { get; set; }
public System.DateTime Time { get; set; }
}
If you want to exclude a type from the model, use the NotMapped attribute or
the DbModelBuilder.Ignore fluent API.
modelBuilder.Ignore<Department>();
Primary Key Convention
Code First infers that a property is a primary key if a property on a class is named “ID” (not case
sensitive), or the class name followed by "ID". If the type of the primary key property is numeric
or GUID it will be configured as an identity column.
C#Copy
public class Department
{
// Primary key
public int DepartmentID { get; set; }
...
}
Relationship Convention
In Entity Framework, navigation properties provide a way to navigate a relationship between two
entity types. Every object can have a navigation property for every relationship in which it
participates. Navigation properties allow you to navigate and manage relationships in both
directions, returning either a reference object (if the multiplicity is either one or zero-or-one) or a
collection (if the multiplicity is many). Code First infers relationships based on the navigation
properties defined on your types.
In addition to navigation properties, we recommend that you include foreign key properties on the
types that represent dependent objects. Any property with the same data type as the principal
primary key property and with a name that follows one of the following formats represents a
foreign key for the relationship: '<navigation property name><principal primary key property
name>', '<principal class name><primary key property name>', or '<principal primary key
property name>'. If multiple matches are found then precedence is given in the order listed above.
Foreign key detection is not case sensitive. When a foreign key property is detected, Code First
infers the multiplicity of the relationship based on the nullability of the foreign key. If the property
is nullable then the relationship is registered as optional; otherwise the relationship is registered as
required.
If a foreign key on the dependent entity is not nullable, then Code First sets cascade delete on the
relationship. If a foreign key on the dependent entity is nullable, Code First does not set cascade
delete on the relationship, and when the principal is deleted the foreign key will be set to null. The
multiplicity and cascade delete behavior detected by convention can be overridden by using the
fluent API.
In the following example the navigation properties and a foreign key are used to define the
relationship between the Department and Course classes.
public class Department
{
// Primary key
public int DepartmentID { get; set; }
public string Name { get; set; }

// Navigation property
public virtual ICollection<Course> Courses { get; set; }
}
public class Course
{
// Primary key
public int CourseID { get; set; }

public string Title { get; set; }


public int Credits { get; set; }
// Foreign key
public int DepartmentID { get; set; }
// Navigation properties
public virtual Department Department { get; set; }
}
Note
If you have multiple relationships between the same types (for example, suppose you define
the Person and Book classes, where the Person class contains
the ReviewedBooks and AuthoredBooks navigation properties and the Book class contains
the Author and Reviewer navigation properties) you need to manually configure the relationships
by using Data Annotations or the fluent API. For more information, see Data Annotations -
Relationships and Fluent API - Relationships.
Complex Types Convention
When Code First discovers a class definition where a primary key cannot be inferred, and no
primary key is registered through data annotations or the fluent API, then the type is automatically
registered as a complex type. Complex type detection also requires that the type does not have
properties that reference entity types and is not referenced from a collection property on another
type. Given the following class definitions Code First would infer that Details is a complex type
because it has no primary key.
C#Copy
public partial class OnsiteCourse : Course
{
public OnsiteCourse()
{
Details = new Details();
}

public Details Details { get; set; }


}

public class Details


{
public System.DateTime Time { get; set; }
public string Location { get; set; }
public string Days { get; set; }
}
Connection String Convention
To learn about the conventions that DbContext uses to discover the connection to use
see Connections and Models.
Removing Conventions
You can remove any of the conventions defined in the
System.Data.Entity.ModelConfiguration.Conventions namespace. The following example
removes PluralizingTableNameConvention.
public class SchoolEntities : DbContext
{
...
protcted override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure Code First to ignore PluralizingTableName convention
// If you keep this convention, the generated tables
// will have pluralized names.
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Custom Conventions
Custom conventions are supported in EF6 onwards. For more information see Custom Code First
Conventions.

CODE FIRST DATA ANNOTATIONS


The Entity Framework Code First approach allows us to use our POCO (domain) classes as a
model and Entity Framework can use the classes to query data, change tracking, and other update
functions.
Entity Framework Code First provides a set of data annotation attributes that can be applied to
domain classes or the properties of domain classes.
Normally we can divide these data annotations into the following two categories.
1. Database Schema-related Attributes
o Table
o Column
o Key
o Timestamp
o ConcurrencyCheck
o ForeignKey
o InverseProperty
o Index
o DatabaseGenerated
o ComplexType
o NotMapped
2. Validation Attributes
o Required
o MinLength
o MaxLength
o StringLength
Table Attribute
Table attributes specify the name of the table and define the schema. This means that this attribute
can be used when the entity name and table name in the database are different.
[Table("Department", Schema = "dbo")]
public class DepartmentMaster
{
// Add your class properties and methods here
}
In the preceding example, my entity name is “DepartmentMaster” and my database table name is
“Department”.
Column Attribute
The same as the table attribute, this attribute specifies the name of the column and the data type of
the column. This means that this attribute is very useful when the entity's property name and the
table's column name are different.
The following are some important properties of the Column Attribute.
 Order: Order in which a column appears in the table.
 TypeName: Name the database type of the column.
Example
[Table("Employee", Schema = "dbo")]
public class Employee
{
[Column("ID", Order = 1)]
public int EmployeeId { get; set; }

[Column("Name", Order = 2, TypeName = "varchar(100)")]


public string EmployeeName { get; set; }
}
Key Attribute
Entity Framework believes that every entity has a primary key and that key is used for tracking
the entities. The Key Attribute specifies the property/column that is the part of the primary key of
the entity and it applies only to scalar properties.
Example
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Table("Department", Schema = "dbo")]
public class DepartmentMaster
{
[Key]
public int DepartmentId { get; set; }
}
Composite keys
An Entity Framework Code First model also supports a composite primary key (a composite
primary key has more than one property).
Example
[Table("Department", Schema = "dbo")]
public class DepartmentMaster
{
[Key]
public int DepartmentId { get; set; }

[Key]
public int CompanyId { get; set; }
}
Timestamp Attribute
The Timestamp attribute specifies the byte array (byte []) property/column that has a concurrency
mode of "Fixed" in the model and it should be a Timestamp column in the stored model
(database).
Example
[Timestamp]
public byte[] TimeStamp { get; set; }
ConcurrencyCheck Attribute
The ConcurrencyCheck Attribute is used to specify a property/column that has a concurrency
mode of “fixed” in the EDM model. This attribute can be used with scalar properties only. A fixed
concurrency mode means that this property is a part of the concurrency check during save
operations.
Example
[ConcurrencyCheck]
public string Name { get; set; }
ForeignKey Attribute
This attribute specifies the foreign key for the Navigation property.
Example
[Table("Employee", Schema = "dbo")]
public class Employee
{
[Column("ID", Order = 1)]
public int EmployeeId { get; set; }

[Column("Name", Order = 2, TypeName = "varchar(100)")]


public string EmployeeName { get; set; }

[ForeignKey("DepartmentId")]
public int DepartmentId { get; set; }

[ForeignKey("DepartmentId")]
public DepartmentMaster Department { get; set; }
}
InverseProperty Attribute
A relationship in the Entity Framework always has two ends, a navigation property on each side
and an Entity Framework that maps them together automatically by convention. If there are
multiple relationships between the two entities, Entity Framework cannot handle the relationships.
This is because Entity Framework doesn't know which navigation property map with which
properties on another side. For example, an Employee is bound with two departments one is the
primary and the other is the secondary. In this scenario, Entity Framework does not know which
navigation properties on the opposite side should be returned.
Using an InverseProperty attribute, we can specify which navigation property should be returned.
Example
[Table("Department", Schema = "dbo")]
public class DepartmentMaster
{
[Key]
public int DepartmentId { get; set; }

[Required]
public string Code { get; set; }

[MinLength(5)]
[MaxLength(100)]
[Index("IX_Name_DepartmentMaster", IsClustered = false, Order = 2)]
public string Name { get; set; }

public ICollection<Employee> PrimaryEmployees { get; set; }


public ICollection<Employee> SecondaryEmployees { get; set; }
}

[Table("Employee", Schema = "dbo")]


public class Employee
{
[Column("ID", Order = 1)]
public int EmployeeId { get; set; }
[Column("Name", Order = 2, TypeName = "varchar(100)")]
public string EmployeeName { get; set; }
[InverseProperty("PrimaryEmployees")]
public DepartmentMaster PrimaryDepartment { get; set; }
[InverseProperty("SecondaryEmployees")]
public DepartmentMaster SecondaryDepartment { get; set; }
}
Index Attribute
An index data annotation attribute is introduced with Entity Framework 6.1. The property of the
model can be marked with an attribute and it should participate in a store index. The Index
attribute allows us to create an index on one or more columns and we can specify the name of the
index.
Example
[Index("IX_Name_DepartmentMaster", IsClustered = false)]
public string Name { get; set; }
C#
DatabaseGenerated Attribute
The DatabaseGenerated attribute specifies that the property of the model will be used for either
identity or Computed column of the database table so that this property will be read-only and the
Entity Framework does not try to update this field into the database table. The Entity Framework
will update this field from the database after the insert or update.
Example
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime DateCreated { get; set; }
C#

ComplexType Attribute
The Complex types are the non-scalar properties of an entity that enable scalar properties to be
organized within the entities. A Complex type may have scalar properties or other complex type
properties. Complex types do not have a key and Identity so Entity Framework cannot manage
these objects apart from the parent entity. A Complex type entity can be also used for a Stored
Procedure result.
Example
[ComplexType]
public class UserInfo
{
public DateTime CreatedDate { get; set; }
public string CreatedBy { get; set; }
}
[Table("Department", Schema = "dbo")]
public class DepartmentMaster
{
[Key]
public int DepartmentId { get; set; }
// Other properties...

public UserInfo User { get; set; }


}
C#
NotMapped Attribute
In the Code First model approach, every property of the model is represented as a table column in
the database. This is not always the case, we might require some property in a model or entity that
is not present in the database table. For example, my Department entity has a property called
DepartmentCodeName, this property returns a combination of code and name separated by a
colon(:). This property can be created dynamically and there is no need to store it in the database.
We can mark this property with NotMapped annotation. In short, if we decorate any property or
class with this attribute then they should be excluded from database mapping.
Example
public class DepartmentMaster
{
[NotMapped]
public string DepartmentCodeName
{
get
{
return Code + ":" + Name;
}
}
// Other members of DepartmentMaster
}

[NotMapped]
public class InternalClass
{
public int Id { get; set; }
public string Name { get; set; }
}
Required Attribute
The Required attribute tells the Entity Framework that this property must have a value and this
attribute will force the Entity Framework to ensure that this has data in it. This attribute will also
participate in database creation (by marking this column as “not nullable”).
Example
[Required]
public string Code { get; set; }
C#

MinLength Attribute
This attribute is used to validate a property, whether the property has a minimum length of string.
Example
[MinLength(5)]
public string Name { get; set; }
MaxLength Attribute
The maxlength attribute allows us to specify additional property validations to set the maximum
length of the string. This attribute will also participate in database creation (by setting the length
of the property).
Example
[MinLength(5)]
[MaxLength(100)]
public string Name { get; set; }
StringLength Attribute
StringLength is used to specify the maximum length of the string. This attribute is applied only to
string-type properties. We can also specify a minimum length of characters that are allowed in the
data field. This attribute will also participate in database creation (by setting the length of the
property).
Example
[StringLength(100, MinimumLength = 5)]
public string Name { get; set; }

DATABASE INITIALIZER

The Code-First approach allows you to define model classes as per the Domain requirements.
Hence, you have complete control over the classes being written or implemented.

In the code-first approach the user who is working will only concentrate on creating classes,
models, and writing code, the rest of the work like creating a database, creating tables, assigning
keys, etc, will be looked over by the Entity framework.

Thus here the developer will not get the overload of backend works.

The Code-First approach has there own principle or strategy. These strategies are the main
backbone of the code-first approach. These strategies are also called database Initializers.

Before going deep into the code, firstly, I would like to give a brief introduction about what
these approaches are.

Here, I have explained the Database initializers and how they work in creating and updating
records in the model.

To add initializers to our dbcontext we need the following things in dbcontext class.
For using all these we need a namespace that is using System.Data.Entity;
So here I am explaining each and every database initializer and how we can use them in our
project.
1. CreateDatabaseIfNotExists:
This is the default initializer class used by the Code-First approach, When the application
starts, this initializer checks for the required model database. If it is not found it will create
the database. Suppose we have created a new project and added a model with different
property. Now we will create a controller, that include all CRUD operation views and a
dbcontext.
Suppose, I have these 3 properties in my model. For this create a new project as in the
following screenshot.

Select a project and then select MVC 4 template.


Click Ok and select the following template.

Now add a model as in the following.


Now add a controller.
Now run your application.

Here as per our model, we can see the two fields in the view.

Now when we add a record it will get saved in our local database and shown as follows.
Now when we will check server explorer a database will automatically get created and inside
that, a table of employee created automatically and the record will be added there.

Now when we will check employee table we will get the record.

Thus as the default database initializer is CreateDatabaseIfNotExists as there is no database in


starting it will create the database and table itself.

2. DropCreateDatabaseWhenModelChanges:

As the name suggests this database initializer will drop the table each time you change the
model. The main demerit of this database initializer is that the previous data you saved in the
table will delete. Here I am explaining how it will work.
Here I have added one more field to the model.
Now here I have compared the two models.

Now, I will build the solution and overwrite the controller. And initialise
the "DropCreateDatabaseWhenModelChanges".to the datacontext constructor.

Now, I will override my controller for updating the view for new property and one record.
When I click to add this data it will be shown as follows.

But here we are unable to see the first record which we have uploaded. This is because when
we run this application the "DropCreateDatabaseWhenModelChanges" initializer first
drops the table and then creates a new table. When we check the local table the only record
which we have inserted will show.

3. DropCreateDatabaseAlways:
This strategy of code first approach creates the database every time you run the application.
If the database already exists and there is no modification done in the model, it will drop the
database and create a new one. In this approach, you will also lose the data.
Now here I am changing the database initializer to DropCreateDatabaseAlways as in the
following screenshot,

Now just build the application and run it.


Add a new record and press the Create button.
Now the record will be added to the view and shown as follows.

Now here also we can see that the previous record also deleted.

Thus in both of these approaches, the saved data will be lost.

The above three databases initializing approach fails when you add new model classes or
property to the existing model. To overcome the demerits of Entity-framework code first approach
a new concept called “Entity-framework code first Migration” came into picture.

CODE FIRST MIGRATIONS


If you understand Code First Entity Framework then this article is easy to understand the concept
of Code First Migration in Entity Framework. If you are unfamiliar with Code First then read this
article Code First Entity Framework.
Code First Migration
You have created a database as per the domain requirements and you forgot a column that must
exist in the table. You check and the column is not present. You then need not create and delete
the existing model to add the new column or table in the database when this approach is used.
Code First Migrations allow you to create a new database or update an existing database based on
your model classes using the Package Manager Console for running commands.
If you are using the EF code first approach then there are more ways to initialize the database
provided by the Entity Framework as follows.
1. DropCreateDatabaseAlways. This database initializer class always drops and creates a new
database, whether it is already present or not with every run of the application.
2. DropCreateDatabaseWhenModelChanges. This database initializer class drops the existing
database and re-creates it if there is a mismatch between the model classes and table schema.
3. CreateDatabaseIfNotExists.
This class creates a database only if it doesn't exist. It avoids any accidental deletion of the
database.
These three databases to be initialized are provided by EF fail when you are updating the model or
classes and then it mismatches when it fails and your database records are lost. Here is one
solution for this, EF Code First Migration. Using the approach you can change the model class or
table or add new classes. Then no database records are lost and your existing database is also the
same.
Creating Model and Database
For using this code first migration you need a database and code, first model. Use the procedure
for creating the code first model.
1. Open Microsoft Visual Studio.
2. "File" -> "New" -> "Project...".
3. Set the Console Application name as CodeFirstMigration.
4. Click OK.
5. Add the EntityFramework NuGet package.
6. Tools -> Library Package Manager –> Package Manager Console
7. Run the Install-Package EntityFramework command. See the output below:

See the following red color box that shows the added references for EntityFramework and
database:
8. Add a new class named EmployeeContext.cs to our Entity Framework Code First Context
and add the following code. Code for EmployeeContext class file:
9. using System;
10. using System.Collections.Generic;
11. using System.Data.Entity;
12. using System.Linq;
13. using System.Text;
14. using System.Threading.Tasks;
15.
16. namespace CodeFirstMigration
17. {
18. public class EmployeeContext : DbContext
19. {
20. public DbSet<Employee> Employees { get; set; }
21. }
22.
23. public class Employee
24. {
25. public int EmployeeID { get; set; }
26. public string EmpName { get; set; }
27. }
}
28. Now we have a model. It's time to do some operation for data access. Add some code to the
Program.cs file as in the following: Code for Program class file:
29. using System;
30. using System.Collections.Generic;
31. using System.Linq;
32. using System.Text;
33. using System.Threading.Tasks;
34. namespace CodeFirstMigration
35. {
36. class Program
37. {
38. static void Main(string[] args)
39. {
40. using (var context = new EmployeeContext())
41. {
42. //Insert values in database
43. context.Employees.Add(new Employee { EmployeeID = 1, EmpName = "krishna" });
44. context.Employees.Add(new Employee { EmployeeID = 2, EmpName = "radha" });
45. context.SaveChanges();
46. //Get all values from database
47. foreach (var emp in context.Employees)
48. {
49. Console.WriteLine("Employee ID : " + emp.EmployeeID);
50. Console.WriteLine("Employee Name : " + emp.EmpName);
51. }
52. }
53. Console.WriteLine("Press Any key to exit....");
54. Console.ReadKey();
55. }
56. }
}
57. Save the changes and Run. The output is as in the following:
58. See in the SQL Server and SQL Server Object Explorer your
model CodeFirstMigration.EmployeeContext.

Until now we just created the model and added records to the database. The actual concept of
Code First Migration is as follows.
1. Make some more changes to our model. Add a new property Role to the Employees table.
public string Role { get; set; }
2. Run the application. You will not get the error “InvalidOperationException” like the
following:

3. Now it's time to use the Code First Migration approach.


4. Open Package Manager Console.
5. Run Enable-Migrations command in a Package Manager console.

6. This command added two more classes to your project in the Migrations folder.
o 201411061912454_InitialCreate.cs This migration was generated because Code First
already created a database for us before we enabled migrations.
o Configuration.cs It allows you to configure how Migrations behave for your context.

7. Update the database with the new changes we made in the model.
8. Run Add-Migration MigrationForRoleInEmp in a Package Manager console.
Now it adds one more class to the Migrations folder in MigrationForRoleInEmp.cs. Let's
use Update-Database to apply this migration to the database.

9. Run the Update-Database command in a Package Manager console.

Code First Migrations will compare the migrations in our Migrations folder with the ones that
have been applied to the database. It will see that the MigrationForRoleInEmp migration
needs to be applied and run it. Finally, CodeFirstMigration.EmployeeContext database is
now updated to include the Role column in the Employees table. See the following image:

Entity Framework supports the following three methods to load related data.
 Eager Loading
 Lazy Loading
 Explicit Loading
Eager Loading
In Eager Loading, all relevant data for an entity is loaded at the time of the query of the entity in
the context object. Eager Loading can be done by using the "Include" method. To perform Eager
Loading, Lazy Loading must be disabled. Lazy Loading is enabled by default in Entity
Framework.

Example
Suppose I have the three tables DepartmentMaster, EmployeeMaster, and EmployeeDetails. The
relation among these three tables is shown in the following diagram.

Example Code
using (var context = new Entities())
{
Console.WriteLine("Eager Loading Example....");
var dep = context.DepartmentMasters
.Include(dm => dm.EmployeeMasters)
.FirstOrDefault(f => f.DepartmentId == 1);
foreach (var emp in dep.EmployeeMasters)
{
Console.WriteLine(emp.Code);
}
Console.ReadKey();
}
Output
Eager Loading at multiple levels
We can also eagerly load multiple levels of related entities. In the following example, it loads the
related entity Department, Employee Master, and Detail.
Sample Code
using (var context = new Entities())
{
Console.WriteLine("Eager Loading Example....");
var dep = context.DepartmentMasters
.Include(dm => dm.EmployeeMasters.Select(em => em.EmployeeDetail))
.FirstOrDefault(f => f.DepartmentId == 1);
foreach (var emp in dep.EmployeeMasters)
{
Console.WriteLine($"Code: {emp.Code} Email Address:
{emp.EmployeeDetail.PersonalEmail}");
}
Console.ReadKey();
}
Output

Lazy Loading
Lazy Loading means delayed loading of the related entities. In Lazy Loading, a related entity or
collection of entities is loaded from the database for the first time that a property is referred to or
the entity is accessed.
Sample code
using (var context = new Entities())
{
context.Configuration.LazyLoadingEnabled = true; // If using DbContext
Console.WriteLine("Lazy Loading Example....");
var dep = context.DepartmentMasters
.Include(dm => dm.EmployeeMasters.Select(em => em.EmployeeDetail))
.FirstOrDefault(f => f.DepartmentId == 1);
foreach (var emp in dep.EmployeeMasters)
{
Console.WriteLine($"Code: {emp.Code} Email Address:
{emp.EmployeeDetail.PersonalEmail}");
}
Console.ReadKey();
}

Output
In the code above, initially, one query is fired to fetch Department Master data. When the
Employee Masters property of the Department is accessed, the Entity Framework loads the related
data automatically. In short, whenever the navigation property is accessed, the Entity Framework
loads the related entity from the database. In the example above if one department has two
employees then the for loop retrieves the related employee as well as the employee details table
from the database.
Explicit Loading
If Lazy Loading is disabled then it is still possible to fetch the related entities without the use of
Eager Loading. It is possible with Explicit Loading. To explicitly retrieve the related entities from
the database we can use the "Load" method. In the following example, If Lazy Loading is disabled
then when I check whether the employee has related detail data it returns null.
Output
using (var context = new Entities())
{
context.Configuration.LazyLoadingEnabled = false; // If using DbContext
var emp = context.EmployeeMasters.FirstOrDefault(p => p.EmployeeId == 1);
if (emp.EmployeeDetail == null)
{
Console.WriteLine("No Employee Detail Data or Employee Detail is not loaded");
}
Console.ReadKey();
}

Now I want to load the related detail data explicitly. There is a one-to-one relationship between
EmployeeMaster and the EmployeeDetail entity. The following will explicitly load one-to-one
related entities
using (var context = new Entities())
{
var emp = context.EmployeeMasters.FirstOrDefault(p => p.EmployeeId == 1);
if (emp.EmployeeDetail == null)
{
Console.WriteLine("No Employee Detail Data or Employee Detail is not loaded");
Console.WriteLine("Loading Employee Detail Data....");
if (!context.Entry(emp).Reference(e => e.EmployeeDetail).IsLoaded)
{
context.Entry(emp).Reference(e => e.EmployeeDetail).Load();
Console.WriteLine("Employee Detail Data load Complete....");
Console.WriteLine("Employee Email: " + emp.EmployeeDetail.PersonalEmail);
}
}
Console.ReadKey();
}
Output

The following will explicitly load one-to-many related entities


using (var context = new Entities())
{
var dep = context.DepartmentMasters.FirstOrDefault(p => p.DepartmentId == 1);
Console.WriteLine("Department Employees are not currently loaded");
if (!context.Entry(dep).Collection(d => d.EmployeeMasters).IsLoaded)
{
context.Entry(dep).Collection(d => d.EmployeeMasters).Load();
Console.WriteLine("Department Employees load complete");
foreach (var emp in dep.EmployeeMasters)
{ Console.WriteLine(emp.Code);
} }
Console.ReadKey(); }
Output

You might also like