实体框架 - 异步查询



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

  • 实体框架 6.0 支持用于查询和保存数据的异步操作。

  • 异步操作可以帮助您的应用程序以以下方式改进:

    • 使您的应用程序对用户交互更具响应性
    • 提高应用程序的整体性能
  • 您可以通过多种方式执行异步操作。但是,async/await 关键字是在 .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 以标记为async 并返回一个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 开始将新学生推送到数据库,然后 DatabaseOperations 方法返回(即使它尚未完成执行)并且 Main 方法中的程序流程继续。

  • 然后消息写入控制台。

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

  • SaveChanges 完成。

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

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

广告