Asynchronous Programming with Entity Framework

Asynchronous Programming with Entity Framework

In this article, I am going to discuss Working with Asynchronous Programming with Entity Framework. Please read our previous article where we discussed how to work with Disconnected Entity in Entity Framework. Asynchronous operations are used to avoid blocking a thread while the query is executed in the database. At the end of this article, you will understand how to perform Asynchronous CRUD Operation using Entity Framework.

Note: We are going to work with the same example that we created in our Introduction to Entity Framework Database First Approach article. Please read our introduction to Entity Framework Database First article before proceeding to this article.

Why do we need Asynchronous Programming?

Asynchronous Programming has been introduced in .NET 4.5. Asynchronous Programming allows executing operations in the background so that the main thread can continue to execute its own operations. In this way, the main thread can keep the user interface responsive while the background thread is processing the task at hand.

Entity Framework 6.x supports asynchronous operations for both querying and saving of data. That means Entity Framework allows us to execute a query and command asynchronously using an instance of DbContext

The advantages of using Asynchronous operations in an application are as follows:

  1. It will make your application more responsive to user interactions
  2. It will improve the overall performance of your application

You can execute asynchronous operations in various ways. But async/await keywords were introduced in .NET Framework 4.5 which makes your job simple.

Using Async/Await:

In the same DbContext object, the async and await keywords are defined by the .NET framework with which we can easily perform the asynchronous programming. The asynchronous methods are useful for both desktops as well as web applications. In order to understand, how to use async and await in C#, please have a look at the below image.

Asynchronous Programming with Entity Framework

As you can see in the image, we use two keywords i.e., async and await to perform asynchronous operations. We have also used some LINQ queries in the code that we will explain later part in this article.

Asynchronous Query in Entity Framework

For a better understanding of the asynchronous queries, please have a look at the below image which is an example of the async method that executes a LINQ-to-Entity query asynchronously and returns the result.

Asynchronous Query in Entity Framework

As you can see in the above image, the GetStudent(int StudentId) method is declared with the async keyword, which makes the GetStudent(int StudentId) method an asynchronous method. The return type of the asynchronous method must be Task<T>. As the GetStudent() method is going to return an object of the Student entity, so the return type here is Task<Student> type.

Further, if you notice in the above image, the LINQ-to-Entity query is also marked with the await keyword. This frees up the calling thread to execute other code until it executes the query and returns the result. Here, we have used FirstOrDefaultAsync async extension method to get the result. You may use other async methods such as SingleOrDefaultAsync, ToListAsyn, etc. that we will see later part of this article.

The complete Example is given below:
using System;
using System.Data.Entity;
using System.Threading.Tasks;

namespace DBFirstApproach
{
    class Program
    {
        static void Main(string[] args)
        {
            var query = GetStudent(1);
            Console.WriteLine($"Doing Some Other Task");
            var student= query.Result;
            Console.WriteLine($"Name: {student?.FirstName} {student?.LastName}");
            Console.Read();
        }

        private static async Task<Student> GetStudent(int StudentId)
        {
            Student student = null;
            using (var context = new EF_Demo_DBEntities())
            {
                Console.WriteLine("GetStudent Method Started...");
                student = await (context.Students.FirstOrDefaultAsync(s => s.StudentId == StudentId));
                Console.WriteLine("GetStudent Method Completed...");
            }
            return student;
        }
    }
}

Output:

Why do we need Asynchronous Programming?

Asynchronous Save using Entity Framework

The Entity Framework API provides the SaveChangesAsync() method to save entities to the database asynchronously. For better understanding, please have a look at the below image which shows an example of saving a Student Entity to the database asynchronously.

Asynchronous Save using Entity Framework

The Complete Code is given below.
using System;
using System.Threading.Tasks;

namespace DBFirstApproach
{
    class Program
    {
        static void Main(string[] args)
        {
            var student = new Student()
            {
                FirstName = "James",
                LastName = "Smith",
                StandardId = 1
            };
            SaveStudent(student);
            Console.WriteLine("Doing Some Other task");
            Console.Read();
        }

        private static async Task SaveStudent(Student newStudent)
        {
            using (var context = new EF_Demo_DBEntities())
            {
                Console.WriteLine("SaveStudent Method Started...");
                context.Students.Add(newStudent);
                await (context.SaveChangesAsync());
                Console.WriteLine("SaveStudent Method Completed...");
            }
        }
    }
}

Output:

Asynchronous Programming in EF

Getting the async Query Result and Save Student Async

We have already discussed two examples. In the first example, we get the result using query and in the second example, we save the student entity using the async query. This example is a combination of both. In the following example first, we execute an async query to get the result and then modify the student entity and saving that modified student entity using the async query.

using System;
using System.Threading.Tasks;
using System.Data.Entity;
namespace DBFirstApproach
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("AsyncQueryAndSave Method Started");
            AsyncQueryAndSave(1);
            Console.WriteLine("AsyncQueryAndSave Method Completed");
            Console.Read();
        }

        public static void AsyncQueryAndSave(int StudentId)
        {
            var query = GetStudent(StudentId);
            Console.WriteLine("Do something else untill get the GetStudent query result..");
            query.Wait();
            var student = query.Result;
            student.FirstName = "Steve";
            student.LastName = "Smith";

            var studentSaveQuery = SaveStudent(student);
            Console.WriteLine("Do something else untill save the modified student entity");
            studentSaveQuery.Wait();
            var saveStudentResult = studentSaveQuery.Result;
            Console.WriteLine($"Student Entity : {saveStudentResult}" );
        }

        private static async Task<Student> GetStudent(int StudentId)
        {
            Student student = null;
            using (var context = new EF_Demo_DBEntities())
            {
                Console.WriteLine("GetStudent Method Started...");
                student = await (context.Students.FirstOrDefaultAsync(s => s.StudentId == StudentId));
                Console.WriteLine("GetStudent Method Completed...");
            }
            return student;
        }

        private static async Task<string> SaveStudent(Student newStudent)
        {
            using (var context = new EF_Demo_DBEntities())
            {
                Console.WriteLine("SaveStudent Method Started...");
                context.Students.Add(newStudent);
                await (context.SaveChangesAsync());
                Console.WriteLine("SaveStudent Method Completed...");
            }
            return "Student Saved Successfully";
        }
    }
}

Output:

Getting the async Query Result and Save Student Async

In the above example, first, we called the async GetStudent(int StudentId) method and stores the reference in the query variable. This will start to execute the GetStudent() method but frees the calling thread so that it can execute further statements in the AsyncQueryAndSave method. The query.wait() method holds the execution until the asynchronous method completes. Once it completes, we can get the result using the variable query.Result. In the same way, the asynchronous save method is called and gets the result.

Asynchronous Delete in Entity Framework

In this case, first, you need to remove the entity from the context object which will mark the entity state as Deleted and when we call the SaveChangesAsync() method, it will remove the entity from the database asynchronously. For better understanding, please have a look at the following example.

using System;
using System.Threading.Tasks;
namespace DBFirstApproach
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("AsyncQueryAndSave Method Started");
            var deleteAsyncQuery = DeleteStudentAsync(1);
            Console.WriteLine("Doing Some other task");
            deleteAsyncQuery.Wait();
            var deleteAsyncResult = deleteAsyncQuery.Result;
            Console.WriteLine($"deleteAsyncResult: {deleteAsyncResult}");
            Console.WriteLine("AsyncQueryAndSave Method Completed");
            Console.Read();
        }

        public static async Task<string> DeleteStudentAsync(int StudentId)
        {
            using (var context = new EF_Demo_DBEntities())
            {
                Console.WriteLine("DeleteStudentAsync Method Started...");
                Student DeleteStudent = await context.Students.FindAsync(StudentId);
                context.Students.Remove(DeleteStudent);
                await (context.SaveChangesAsync());
                Console.WriteLine("DeleteStudentAsync Method Completed...");
            }
            return "Student Deleted Successfully";
        }
    }
}

Note: If the student you are trying to delete having any foreign key relationship data, then it will not allow you to delete the student. In such cases first, you need to delete foreign key table data and then delete the student data.

Points to Remember while working with Asynchronous Programming:

Three important points to remember while working with Asynchronous Programming. They are as follows:

  1. The Async programming is primarily focused on freeing up the current managed thread (thread running .NET code) to do other work while it waits for an operation that does not require any compute time from a managed thread. For example, the database engine is processing a query there is nothing to be done by .NET code.
  2. In client applications (WinForms, WPF, etc.) the current thread can be used to keep the UI responsive while the async operation is performed. In server applications (ASP.NET, ASP.NET MVC, ASP.NET Web API, etc.) the thread can be used to process other incoming requests – this can reduce memory usage and/or increase the throughput of the server.
  3. In most applications using async will have no noticeable benefits and even could be detrimental. Use tests, profiling, and common sense to measure the impact of async in your particular scenario before committing to it.

In the next article, I am going to discuss Bulk Insert, Update, and Delete i.e. How to add, remove, and update multiple entities in Entity Framework. Here, in this article, I try to explain Working with Asynchronous Programming with Entity Framework and I hope you enjoyed this Asynchronous Programming with Entity Framework article. Please give your valuable feedback and suggestions about this article.

Leave a Reply

Your email address will not be published. Required fields are marked *