Asynchronous Querying and Saving in EF 6

Asynchronous execution has been introduced in .NET 4.5 which can be useful in Entity Framework. EF 6 allows us to execute a query and command asynchronously using an instance of DbContext.

Let's see how to execute asynchronous queries first and then, we will see an asynchronous call to context.SaveChanges.

Asynchronous Query

The following is an example of the async method which executes a LINQ-to-Entity query asynchronously and returns the result.

private static async Task<Student> GetStudent()
{
    Student student = null;

    using (var context = new SchoolDBEntities())
    {
        Console.WriteLine("Start GetStudent...");
              
        student = await (context.Students.Where(s => s.StudentID == 1).FirstOrDefaultAsync<Student>());
            
        Console.WriteLine("Finished GetStudent...");
    }

    return student;
}

As you can see in the above code, the GetStudent() method is marked with the async keyword, which makes it an asynchronous method. The return type of the asynchrounous method must be Task<T>. The GetStudent() method returns an object of the Student entity, so return type must be of Task<Student> type.

Also, the LINQ query is marked with the await keyword. This frees up the calling thread to execute other code until it executes the query and returns the result. We have used the FirstOrDefaultAsync async extension method to get the result. You may use other async methods appropriately such as SingleOrDefaultAsync, ToListAsyn etc.

Asynchronous Save

EF API provides the SaveChangesAsync() method to save entities to the database asynchronously. The following SaveStudent method saves the Student entity to the database asynchronously.

private static async Task SaveStudent(Student editedStudent)
{
    using (var context = new SchoolDBEntities())
    {
        context.Entry(editedStudent).State = EntityState.Modified;
                
        Console.WriteLine("Start SaveStudent...");
                
        int x = await (context.SaveChangesAsync());
                
        Console.WriteLine("Finished SaveStudent...");
    }
}

Getting the async Query Result

The following example demonstrates executing an async query, getting the result and saving the modified entity.

public static void AsyncQueryAndSave()
{
    var query = GetStudent();
            
    Console.WriteLine("Do something else here till we get the query result..");

    query.Wait();

    var student = query.Result;
	
    student.FirstName = "Steve";
            
    var numOfSavedStudent = SaveStudent(student);
            
    Console.WriteLine("Do something else here till we save a student.." );

    studentSave.Wait();

    Console.WriteLine("Saved Entities: {0}", numOfSavedStudent.Result);
}
Output
Start GetStudent...
Do something else here till we get the query result..
Finished GetStudent...
Start SaveStudent...
Do something else here till we save a student..
Finished SaveStudent...
Saved Entities: 1

In the above example, the async method GetStudent() is called and it 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.