Mastering Entity Framework - Sample Chapter
Mastering Entity Framework - Sample Chapter
ee
Sa
m
pl
Rahul loves software development, and his interests involve system programming,
website development, and learning/teaching subjects related to computer science /
information systems. He was also awarded CodeProject MVP in 2013 and DZone
MVB in 2014. He blogs regularly about technology on his blog
(www.rahulrajatsingh.com).
I would like to thank my wife and daughter for their love and support and
being patient with the long working hours that enabled me to write this book.
I would like to thank my parents for everything they have done for me.
Everything I am today is because of them. Finally, I would like to thank a
couple of my mentors Mr. Himanshu Agnihotri and Mr. Amalraj P for
supporting me during my struggle period and showing me the right path.
Introduction to
Entity Framework
Entity Framework is an Object Relational Mapper (ORM) from Microsoft that
lets the application's developers work with relational data as business models. It
eliminates the need for most of the plumbing code that developers write (while
using ADO.NET) for data access. Entity Framework provides a comprehensive,
model-based system that makes the creation of a data access layer very easy for
the developers by freeing them from writing similar data access code for all the
domain models. The initial release of Entity Framework was Entity Framework 3.5.
It was released with .NET Framework 3.5 SP1 and Visual Studio 2008 SP1. Entity
Framework has evolved a lot since then, and the current version is 6.0.
Entity Framework eases the task of creating a data access layer by enabling the access
of data, by representing the data as a conceptual model, that is, a set of entities and
relationships. The application can perform the basic CRUD (create, read, update, and
delete) operations and easily manage one-to-one, one-to-many, and many-to-many
relationships between the entities.
Here are a few benefits of using Entity Framework:
The development time is reduced since the developers don't have to write all
the ADO.NET plumbing code needed for data access
We can have all the data access logic written in a higher-level language such
as C# rather than writing SQL queries and stored procedures
From the preceding diagram, we can see that Entity Framework is written on top of
the ADO.NET framework, and underneath, it is still using the ADO.NET methods
and classes to perform the data operations.
[8]
Chapter 1
Keeping track of changes in the models so that the models can be updated in
the database
[9]
The ObjectContext class has a SaveChanges method that we have to call when we
want to save the new or changed objects to the database.
Database First: This is the approach that will be used with an existing
database schema. In this approach, the EDM will be created from the database
schema. This approach is best suited for applications that use an already
existing database.
[ 10 ]
Chapter 1
Code First: This is the approach where all the domain models are written
in the form of classes. These classes will constitute our EDM. The database
schema will be created from these models. This approach is best suited
for applications that are highly domain-centric and will have the domain
model classes created first. The database here is needed only as a persistence
mechanism for these domain models.
Model First: This approach is very similar to the Code First approach, but in
this case, we use a visual EDM designer to design our models. The database
schema and the classes will be generated by this conceptual model. The
model will give us the SQL statements needed to create the database, and
we can use it to create our database and connect up with our application.
For all practical purposes, it's the same as the Code First approach, but in
this approach, we have the visual EDM designer available.
When we are working in a scenario where the database design is being done
by another team of DBAs, and once the database is ready, the application
development starts.
When we are working on a data centric application, that is, the application
domain model is the database itself, and it is being changed frequently to
cater to new requirements. For instance, when the tables are being updated
regularly and new columns are being added to it frequently then we can
simply use this approach, and the application code will not break. We simply
have to write the code to cater to the newly added columns.
[ 11 ]
The database is simply a persistence mechanism for the models, that is, no
logic is in the database.
Full control over the code, that is, there is no auto-generated model and
context code.
The database will not be changed manually. The model classes will always
change and based on this, the database should change itself.
[ 12 ]
Chapter 1
Let's start by defining a database for the ToDo application. Let's create a simple table
that will keep a track of all the ToDo items:
When we add the EDM, it asks us whether we want to create the conceptual model
from the existing database, or if we want to create an empty model. For the Database
First approach, we need to select an existing database. The following screenshot
shows the wizard step that asks you to select the database:
[ 14 ]
Chapter 1
Once we choose to add the EDM, we need to specify the database that should be
used to create it. So, the next step in the wizard will ask you for the connection to the
database. Let's see what this wizard step looks like:
[ 15 ]
Once the connection is successfully established, the wizard shows us all the tables,
views, procedures, and functions that we will want to access from our application.
Using this wizard, we can also choose to include the foreign key relations in our
conceptual model and singularization of the model name, in case the table name
is plural in our conceptual model:
ADO.NET EDM wizard step 3select the schema elements to be included in the EDM
[ 16 ]
Chapter 1
Once the conceptual model is created, the EDM will be created for use in our
application. The application will create a .EDMX file that contains all the information
about our conceptual entity model and its mapping to the database tables:
[ 17 ]
We can modify the conceptual model and change the mapping using entity designer.
Let's try to change the property ToDo1 to ToDoItem in our conceptual model. Note
that only the class property has been changed, and not the column name:
If we open the EDMX file, we can find the following three sections:
Conceptual schema definition: This specifies how a strongly typed model for
our conceptual model will be created:
<edmx:ConceptualModels>
<Schema Namespace="ToDoDBModel" Alias="Self" annotation:UseStron
gSpatialTypes="false" xmlns:annotation="http://schemas.microsoft.
com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.
com/ado/2009/11/edm">
<EntityType Name="ToDo">
<Key>
[ 18 ]
Chapter 1
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Int32" Nullable="false" />
<Property Name="TodoItem" Type="String" MaxLength="Max"
FixedLength="false" Unicode="true" Nullable="false" />
<Property Name="IsDone" Type="Boolean" Nullable="false" />
</EntityType>
<EntityContainer Name="ToDoDBEntities" annotation:LazyLoadingEna
bled="true">
<EntitySet Name="ToDos" EntityType="Self.ToDo" />
</EntityContainer>
</Schema>
</edmx:ConceptualModels>
Storage schema definition: This specifies how the storage model is created,
that is, how the values are stored in the database:
<edmx:StorageModels>
<Schema Namespace="ToDoDBModel.Store" Provider="System.
Data.SqlClient" ProviderManifestToken="2012" Alias="Self"
xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/
EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/
ado/2009/11/edm/ssdl">
<EntityType Name="ToDos">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="int" Nullable="false" />
<Property Name="Todo" Type="nvarchar(max)" Nullable="false" />
<Property Name="IsDone" Type="bit" Nullable="false" />
</EntityType>
<EntityContainer Name="ToDoDBModelStoreContainer">
<EntitySet Name="ToDos" EntityType="Self.ToDos" Schema="dbo"
store:Type="Tables" />
</EntityContainer>
</Schema>
</edmx:StorageModels>
Mapping: This specifies the mapping between the conceptual model and the
storage model:
<edmx:Mappings>
<Mapping Space="C-S" xmlns="http://schemas.microsoft.com/
ado/2009/11/mapping/cs">
<EntityContainerMapping StorageEntityContainer="ToDoDBModelStore
Container" CdmEntityContainer="ToDoDBEntities">
<EntitySetMapping Name="ToDos">
[ 19 ]
Once the EDM is created, we will get a class generated for each model object present
in our conceptual model. We will also get the DBContext class that will let's use these
strongly typed models:
Chapter 1
Now we are ready to write typed queries against the generated conceptual model, and
Entity Framework will execute our queries on the database, and return the results in
the form of these strongly typed models. Creating new data or updating the existing
data is also very easy, because Entity Framework automatically tracks the changes we
make in our models, and lets us save the changes to the database. This can simply be
done by calling the SaveChanges method on the DBContext class. One important thing
to note here is that the read operation can utilize Language-Integrated Query (LINQ)
to query the object data model, and Entity Framework will take care of converting it to
the appropriate SQL query and retrieve the results.
If our application is a data-centric application, and all we need is to be able to
perform CRUD operations using strongly typed objects, this is all that we are going
to need. However, one of the great benefits of Entity Framework is being able
to modify the conceptual models to better adapt to our domain needs, and then
use the mappings to map the domain model to the database tables. We can have
relationships between our domain models and still let them persist the data in a
given set of tables.
In the Database First approach, the Entity Model is able to
incrementally update the conceptual model if the database
schema is updated. We just need to right-click on the visual
designer and chose Update Model from Database.
In the later chapters, we will see how to manage multiple models, how we can define
relationships between the entities, introduce inheritance hierarchies, customize
entities, and much more. This will give you a good foundation to get started with
the Entity Framework Database First approach if you haven't used it before, and will
refresh your memory if you have.
[ 21 ]
[ 22 ]
Chapter 1
Since we are planning to start with an empty model, we have to select an empty
model in the wizard. The following screenshot shows the wizard step that asks you
to select the option. We have to select Empty model in this step:
[ 23 ]
Once we choose the empty model, Entity Framework will show us the Visual Entity
Designer. Now we can add the entities and relations to the designer area from the
toolbar. The Entity Designer and the toolbar will look something like this:
An empty Visual Entity Designer after selecting the Model First approach
Let's try to add a new entity to our ToDo application and add properties to that
model. Let's add a few properties to our ToDo model:
[ 24 ]
Chapter 1
Let's add the scalar properties needed for our ToDo model. Let's make the ID field a
primary key field, a string property for ToDoItem, and a Boolean property for IsDone:
[ 25 ]
Once we have the conceptual model created for our application, we have to create
the database from this conceptual model. This can be done by right-clicking on the
entity and choosing Generate Database from Model:
[ 26 ]
Chapter 1
This will prompt you to select the database connection. This wizard will not create
the actual database, but it will generate the DDL for us, and we will have to use that
DDL to create the database ourselves:
Wizard step to select the connection string to be used for a generated database script
[ 27 ]
After we select the database connection, the wizard will give us the SQL to create the
database on the specified connection:
[ 28 ]
Chapter 1
We can now copy this SQL and create the database. The Entity Framework has
already created connectionString to use this connection, and wired up the
DBContext class to perform the operations on this database. Let's take a look at the
generated DbContext class:
public partial class ToDoModelContainer : DbContext
{
public ToDoModelContainer()
: base("name=ToDoModelContainer")
{
}
public virtual DbSet<ToDo> ToDoes { get; set; }
}
The strongly typed objects will also be generated from the conceptual model. Let's
take a look at our generated ToDo class:
public partial class ToDo
{
public ToDo()
{
this.IsDone = false;
}
public int Id { get; set; }
public string ToDoItem { get; set; }
public bool IsDone { get; set; }
}
If we are using the Model First approach, one important thing to consider is that
the incremental changes in our model will not perform the incremental updates
to the database. Rather, it will give us the SQL to create the updated database from
the ground up.
If we want to perform incremental updates to the database,
we can use the Database Generation Power Pack from Microsoft
(https://visualstudiogallery.msdn.microsoft.com/
df3541c3-d833-4b65-b942-989e7ec74c87/). Using this,
we can perform incremental updates to the database.
[ 29 ]
Once we have the ToDo class ready, we need to start thinking about how the
database will be created from our classes. We need to tell Entity Framework how to
use our classes and generate the database accordingly. We want to tell the database
generation module about all the persistence information, such as table names, key
columns, and so on. We can do this in our model classes. So, if we try to put these
attributes in our model class, our resultant ToDo model will look like this:
[Table("ToDo")] // Table name
public class ToDo
{
[Key] // Primary key
public int Id { get; set; }
[Column("ToDoItem", TypeName="ntext")]
public string ToDoItem { get; set; }
[Column("IsDone", TypeName="bit")]
public bool IsDone { get; set; }
}
[ 30 ]
Chapter 1
In the preceding code, we updated our class with a table attribute passing in the
table name. This will tell the Entity Framework that a table should be created for this
class. Each property of the class can be updated with the Column attribute, and we
can specify the name of the column this property should be mapped to and the data
type. The Key attribute will be used to specify the property that should be used as a
primary key.
Entity Framework uses the DBContext class to save the models to the database. In
the Code First approach, we need to create the DBContext class ourselves too. Let's
see how we can implement our DBContext class:
public partial class ToDoDBContext : DbContext
{
public ToDoDBContext()
: base("name=ToDoConnectionString")
{
}
public DbSet<ToDo> ToDoes { get; set; }
}
The context class that we are creating should be derived from the DbContext class.
The context class will also keep DbSet of ToDos that will represent the list of ToDo
items being retrieved from the table. The constructor of the context class will pass the
name of connectionString to the base DbContext class. This connectionString
will be used to connect to the database.
Another possibility is to keep the name of the connectionString the same as the
DbContext class name. The Entity Framework will be able to use the corresponding
DbContext class with this connectionString to persist the data. This is an example
of the Convention over configurations principle. However, this is also flexible, so that
we have the possibility of giving custom names to the connectionStrings.
Now to be able to use Entity Framework to persist the data, we just need to create
this connectionString in the XML configuration, and Entity Framework will
take care of creating the database and performing the CRUD operations on their
respective models.
This has shown you how to use the Code First approach using a single model. In
later chapters, you will see how to use multiple models and have relationships
between them, how we can define complex types, and customize models as per our
application requirements.
[ 31 ]
Now let's say we have a model for our ToDo item, that is, ToDo. We also have the
DbContext class created to perform CRUD operations on the ToDo model. Let's take a
look at how we can use Entity Framework to perform CRUD operations on our ToDo
model. The important thing to note in these examples would be the use of LINQ. We
will write all our queries in LINQ, and Entity Framework will take care of converting
it to the appropriate SQL and return the results.
Chapter 1
After this call, the list of ToDo items will be available in the ToDo items
collection if we enumerate ToDo items. Entity Framework will internally
perform the following activities for us to fetch the result:
3. Parsed our request for the data.
4. Generated the needed SQL query to perform this action.
5. Used the context class to wire up the SQL to the database.
6. Fetched the results from the database.
7. Created the strongly typed models from the retrieved results and return
them to the user.
If we need to perform eager loading, we can do this by calling
ToList() on the collection as: IEnumerable<ToDo>
todoItems = db.ToDos.ToList();.
[ 33 ]
2. Retrieved an item by passing the key values, that is, using the Find function:
ToDo todo1 = db.ToDos.Find(id);
[ 34 ]
Chapter 1
[ 35 ]
What is happening in the preceding code is that the DbContext class was still in
scope when the entity was being updated and saved. The DbContext class is able
to track the changes in the entity if it is in scope. However, this approach is rarely
useful, because in real applications in a typical n-tier application, the entities will be
passed through multiple layers, and any layer can update this entity, and at the time
of updating the entity, objects are usually disconnected from the context.
So to perform the updates in such a disconnected environment, we need to attach
the updated entity back to let the DbContext class identify the modifications made
in the entity, and then generate the appropriate update SQL accordingly and persist
the updates in the database. This can be done by attaching the entity back to the
DbContext class. Let's see how a ToDo model can be attached to the DbContext class
if it is being passed from a different tier:
using (ToDoDBEntities db = new ToDoDBEntities())
{
db.Entry(todo).State = EntityState.Modified;
db.SaveChanges();
}
2. Attached the model to the DbContext class and marked this model
as modified:
db.Entry(todo).State = EntityState.Modified;
[ 36 ]
Chapter 1
Deleting an item
To delete an item, we just need to fetch the item that needs to be deleted, call the
Remove method on the model collection, and call the SaveChanges method on the
DbContext class. Let's try to delete a model with the ID 3:
using (ToDoDBEntities db = new ToDoDBEntities())
{
int id = 3;
ToDo todo = db.ToDos.Find(id);
db.ToDos.Remove(todo);
db.SaveChanges();
}
It is also possible that the model entities are getting created and deleted
while being disconnected from the DbContext class. In these cases, we
need to attach the models to the DBContext class, and mark them using
the EntityState property.
[ 37 ]
Approach
Database First
Database First
Database First
Model First
Code First
Do we want to write all the model classes, implement them, and then
think about the database storage later?
Code First
Code First
Database First
Summary
In this chapter, we talked about the ORMs and how ORMs can ease the task of
writing data access code. We saw what Entity Framework is and how it works. We
then saw the various approaches for using Entity Framework. We performed CRUD
operations on a simple model to see Entity Framework in action. Finally, we looked
at which approach would better fit our needs based on the given scenario.
In the next chapter, we will see how we can use the Entity Framework Database First
approach to model complex relationships between database tables as relationships
between the domain models. We will also see how to work with these related models
using Entity Framework.
[ 38 ]
www.PacktPub.com
Stay Connected: