Book Image

Mastering Entity Framework

By : Rahul Rajat Singh
Book Image

Mastering Entity Framework

By: Rahul Rajat Singh

Overview of this book

<p>Data access is an integral part of any software application. Entity Framework provides a model-based system that makes data access effortless for developers by freeing you from writing similar data access code for all of your domain models.</p> <p>Mastering Entity Framework provides you with a range of options when developing a data-oriented application. You’ll get started by managing the database relationships as Entity relationships and perform domain modeling using Entity Framework. You will then explore how you can reuse data access layer code such as stored procedures and table-valued functions, and perform various typical activities such as validations and error handling. You’ll learn how to retrieve data by querying the Entity Data Model and understand how to use LINQ to Entities and Entity SQL to query the Entity Data Model.</p>
Table of Contents (19 chapters)
Mastering Entity Framework
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Performing CRUD operations using Entity Framework


We will perform CRUD operations on our ToDo model using the Entity Framework DbContext class.

Tip

It doesn't matter which approach we select to create the database and conceptual model (Database First, Code First, or Model First); from the code perspective, it's the same code that the developers need to write in order to use Entity Framework.

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.

Reading a list of items

The way Entity Framework works is that using the DbContext class, we can retrieve all the data by simply accessing the model collection associated with the view. So, to fetch a list of items, we just need to get the model collection from the context class:

using(ToDoDBEntities db = new ToDoDBEntities())
{
    IEnumerable<ToDo> todoItems = db.ToDos;
}

Let's try to understand the preceding code:

  1. We created an object of the DbContext class:

    ToDoDBEntities db = new ToDoDBEntities();
  2. We then used the DbContext object to fetch the ToDo entities:

    IEnumerable<ToDo> todoItems = db.ToDos;

    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.

    Note

    If we need to perform eager loading, we can do this by calling ToList() on the collection as: IEnumerable<ToDo> todoItems = db.ToDos.ToList();.

Reading a specific item

If we want to retrieve a single item from the model collection, we have many ways of doing it. Typically, we can use any LINQ function to fetch the single record from the model collection. Also, if we want to fetch the result using the primary key, we can use the Find method to do it. Let's look at a few ways in which we can retrieve a single item using Entity Framework:

using (ToDoDBEntities db = new ToDoDBEntities())
{
  ToDo todo1 = db.ToDos.Find(id);

  ToDo todo3 = db.ToDos.FirstOrDefault(item => item.TodoItem == "Test item");
  ToDo todo2 = db.ToDos.SingleOrDefault(item => item.TodoItem == "Test item");    
  

}

Let's try to understand the preceding code:

  1. We created an object of the DbContext class:

    ToDoDBEntities db = new ToDoDBEntities()
  2. Retrieved an item by passing the key values, that is, using the Find function:

    ToDo todo1 = db.ToDos.Find(id);
  3. Retrieved an item by passing a non-key value using the FirstOrDefault function:

    ToDo todo2 = db.ToDos.SingleOrDefault(item => item.TodoItem == "Test item");
  4. Retrieved an item by passing a non-key value using the SingleOrDefault function:

    ToDo todo2 = db.ToDos.SingleOrDefault(item => item.TodoItem == "Test item");

    Tip

    The FirstOrDefault and SingleOrDefault functions will return the first occurrence of the item if it is found, else it will return null. We should always check for the null values before using the item retrieved using these functions. SingleOrDefault will throw an exception if it finds multiple items matching the request criteria.

Creating a new item

To create an item, we simply need to create the model, assign the values in the model properties, and then call the SaveChanges method on Entity Framework. Now let's see how we can create a ToDo item using Entity Framework:

using (ToDoDBEntities db = new ToDoDBEntities())
{
    ToDo todoItem = new ToDo();
    todoItem.TodoItem = "This is a test item.";
    todoItem.IsDone = false;
     db.ToDos.Add(todoItem);

    db.SaveChanges();
}

Let's try to understand the preceding code:

  1. We created an object of the DbContext class:

    ToDoDBEntities db = new ToDoDBEntities()
  2. Created a new ToDo item:

    ToDo todoItem = new ToDo();
  3. Populated the ToDo item properties with the desired values:

    todoItem.TodoItem = "This is a test item.";
    todoItem.IsDone = false;
  4. Added the item to the context class:

      db.ToDos.Add(todoItem);
  5. Called Entity Framework's SaveChanges method to persist these changes in the database:

    db.SaveChanges();

Note

Entity Framework's DbContext class is able to identify a new model and generate the respective insert query for it to create a new record on the database.

Updating an existing item

To update an existing item, there are two possibilities. The first possibility is that we will fetch the model, update some of the properties of the model, and then save the updated model in the database. To do this, we just need to fetch the required model using the DbContext class, update its properties, and then call the SaveChanges method on the DbContext object. Let's try to update a model with the ID 3:

using (ToDoDBEntities db = new ToDoDBEntities())
{
    int id = 3;
    ToDo todo = db.ToDos.Find(id);

    todo.TodoItem = "This has been updated";
    todo.IsDone = false;
    db.SaveChanges();
}

Let's try to understand the preceding code:

  1. We created an object of the DbContext class:

    ToDoDBEntities db = new ToDoDBEntities()
  2. Fetched the item with id = 3:

    int id = 3;
    ToDo todo = db.ToDos.Find(id);
  3. Updated the model properties:

    todo.TodoItem = "This has been updated";
    todo.IsDone = false;
  4. Called Entity Framework's SaveChanges method to persist these changes in the database:

    db.SaveChanges();

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();
}

Let's try to understand the preceding code:

  1. We created an object of the DbContext class:

    ToDoDBEntities db = new ToDoDBEntities()
  2. Attached the model to the DbContext class and marked this model as modified:

    db.Entry(todo).State = EntityState.Modified;
  3. Called Entity Framework's SaveChanges method to persist these changes in the database:

    db.SaveChanges();

    Note

    In the preceding code, the ToDo model is being modified and passed from some other layer. This is a fairly advanced topic and if it is not clear at this stage, please move on; this will be covered in detail in further chapters.

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();
}

Let's try to understand the preceding code:

  1. We created an object of the DbContext class:

    ToDoDBEntities db = new ToDoDBEntities()
  2. Fetched the item with id = 3:

    int id = 3;
    ToDo todo = db.ToDos.Find(id);
  3. Removed the item from the collection:

    db.ToDos.Remove(todo);
  4. Called Entity Framework's SaveChanges method to persist these changes in the database:

    db.SaveChanges();

    Note

    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.