实体框架 - 异步查询


异步编程涉及在后台执行操作,以便主线程可以继续其自己的操作。这样,当后台线程处理手头的任务时,主线程可以保持用户界面响应。

  • Entity Framework 6.0 支持查询和保存数据的异步操作。

  • 异步操作可以通过以下方式帮助您的应用程序 -

    • 使您的应用程序对用户交互更加敏感
    • 提高应用程序的整体性能
  • 您可以通过多种方式执行异步操作。但是 .NET Framework 4.5 中引入了 async/await 关键字,这使您的工作变得简单。

  • 您唯一需要遵循的是异步/等待模式,如以下代码片段所示。

让我们看一下下面的示例(不使用 async/await),其中 DatabaseOperations 方法将新学生保存到数据库,然后从数据库中检索所有学生,最后在控制台上打印一些附加消息。

class Program {

   static void Main(string[] args) {
      Console.WriteLine("Database Operations Started");
      DatabaseOperations();
		
      Console.WriteLine();
      Console.WriteLine("Database Operations Completed");
      Console.WriteLine();
      Console.WriteLine("Entity Framework Tutorials");
		
      Console.ReadKey();
   }

   public static void DatabaseOperations() {

      using (var context = new UniContextEntities()) {

         // Create a new student and save it

         context.Students.Add(new Student {
            FirstMidName = "Akram", 
            LastName = "Khan", 
            EnrollmentDate = DateTime.Parse(DateTime.Today.ToString())});

         Console.WriteLine("Calling SaveChanges.");
         context.SaveChanges();
         Console.WriteLine("SaveChanges completed.");

         // Query for all Students ordered by first name

         var students = (from s in context.Students
            orderby s.FirstMidName select s).ToList();

         // Write all students out to Console

         Console.WriteLine();
         Console.WriteLine("All Student:");

         foreach (var student in students) {
            string name = student.FirstMidName + " " + student.LastName;
            Console.WriteLine(" " + name);
         }
      }
   }
}

执行上述代码时,您将收到以下输出 -

Calling SaveChanges.
SaveChanges completed.
All Student:
Akram Khan
Ali Khan
Ali Alexander
Arturo Anand
Bill Gates
Gytis Barzdukas
Laura  Nornan
Meredith fllonso
Nino Olioetto
Peggy Justice
Yan Li

Entity Framework Tutorials

让我们使用新的 async 和await 关键字并对 Program.cs 进行以下更改

  • 添加 System.Data.Entity 命名空间,该命名空间将提供 EF 异步扩展方法。

  • 添加 System.Threading.Tasks 命名空间,这将允许我们使用 Task 类型。

  • 更新DatabaseOperations以标记为异步并返回Task

  • 调用 SaveChanges 的异步版本并等待其完成。

  • 调用 ToList 的异步版本并等待结果。

class Program {

   static void Main(string[] args) {
      var task = DatabaseOperations();
      Console.WriteLine();
      Console.WriteLine("Entity Framework Tutorials");
      task.Wait();
      Console.ReadKey();
   }

   public static async Task DatabaseOperations() {

      using (var context = new UniContextEntities()) {

         // Create a new blog and save it

         context.Students.Add(new Student {
            FirstMidName = "Salman", 
            LastName = "Khan", 
            EnrollmentDate = DateTime.Parse(DateTime.Today.ToString())});

         Console.WriteLine("Calling SaveChanges.");
         await context.SaveChangesAsync();
         Console.WriteLine("SaveChanges completed.");

         // Query for all Students ordered by first name

         var students = await (from s in context.Students 
            orderby s.FirstMidName select s).ToListAsync();

         // Write all students out to Console

         Console.WriteLine();
         Console.WriteLine("All Student:");

         foreach (var student in students) {
            string name = student.FirstMidName + " " + student.LastName; 
            Console.WriteLine(" " + name);
         }
      }
   }
}

执行时,它将产生以下输出。

Calling SaveChanges.
Entity Framework Tutorials
SaveChanges completed.
All Student:
Akram Khan
Ali Khan
Ali Alexander
Arturo Anand
Bill Gates
Gytis Barzdukas
Laura  Nornan
Meredith fllonso
Nino Olioetto
Peggy Justice
Salman Khan
Yan Li

现在代码是异步的,您可以观察程序的不同执行流程。

  • SaveChanges 开始将新的 Student 推送到数据库,然后 DatabaseOperations 方法返回(即使它尚未完成执行)并且 Main 方法中的程序流继续。

  • 然后消息被写入控制台。

  • 托管线程在 Wait 调用上被阻塞,直到数据库操作完成。一旦完成,我们的数据库操作的其余部分将被执行。

  • SaveChanges 完成。

  • 从数据库中检索所有学生并将其写入控制台。

我们建议您逐步执行上述示例,以便更好地理解。