Асинхронный запрос и сохранение
Примечание.
Только в EF6 и более поздних версиях. Функции, API и другие возможности, описанные на этой странице, появились в Entity Framework 6. При использовании более ранней версии могут быть неприменимы некоторые или все сведения.
EF6 представила поддержку асинхронного запроса и сохранения с помощью асинхронных и ожидающих ключевое слово, появившихся в .NET 4.5. Хотя не все приложения могут воспользоваться асинхронностью, ее можно использовать для повышения скорости реагирования клиентов и масштабируемости сервера при обработке длительных задач, сетевых или сетевых операций ввода-вывода.
Когда действительно использовать асинхронную
Цель этого пошагового руководства — ввести асинхронные понятия таким образом, чтобы было легко наблюдать разницу между асинхронным и синхронным выполнением программы. Это пошаговое руководство не предназначено для иллюстрации любого из ключевых сценариев, в которых асинхронное программирование обеспечивает преимущества.
Асинхронное программирование в основном сосредоточено на освобождении текущего управляемого потока (поток под управлением кода .NET) для выполнения другой работы во время ожидания операции, которая не требует времени вычислений из управляемого потока. Например, в то время как ядро СУБД обрабатывает запрос, не требуется ничего делать с помощью кода .NET.
В клиентских приложениях (WinForms, WPF и т. д.) текущий поток можно использовать для реагирования пользовательского интерфейса при выполнении асинхронной операции. В серверных приложениях (ASP.NET и т. д.) поток можно использовать для обработки других входящих запросов. Это может снизить использование памяти и /или увеличить пропускную способность сервера.
В большинстве приложений, использующих асинхронный код, не будет заметных преимуществ и даже может быть вредным. Используйте тесты, профилирование и здравый смысл, чтобы оценить влияние асинхронного асинхронного сценария перед фиксацией в нем.
Ниже приведены дополнительные ресурсы для получения сведений об асинхронном коде:
- Обзор асинхронного/await Брэндона Брэй в .NET 4.5
- Страницы асинхронного программирования в библиотека MSDN
Создание модели
Мы будем использовать рабочий процесс Code First для создания модели и создания базы данных, однако асинхронная функциональность будет работать со всеми моделями EF, включая созданные с помощью конструктора EF.
- Создание консольного приложения и вызов asyncDemo
- Добавление пакета NuGet EntityFramework
- В Обозреватель решений щелкните правой кнопкой мыши проект AsyncDemo
- Выберите " Управление пакетами NuGet...
- В диалоговом окне "Управление пакетами NuGet" выберите вкладку "Интернет" и выберите пакет EntityFramework
- Щелкните Установить.
- Добавление класса Model.cs со следующей реализацией
using System.Collections.Generic;
using System.Data.Entity;
namespace AsyncDemo
{
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
}
Создание синхронной программы
Теперь, когда у нас есть модель EF, давайте напишите код, который использует его для выполнения доступа к данным.
- Замените содержимое Program.cs следующим кодом.
using System;
using System.Linq;
namespace AsyncDemo
{
class Program
{
static void Main(string[] args)
{
PerformDatabaseOperations();
Console.WriteLine("Quote of the day");
Console.WriteLine(" Don't worry about the world coming to an end today... ");
Console.WriteLine(" It's already tomorrow in Australia.");
Console.WriteLine();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
public static void PerformDatabaseOperations()
{
using (var db = new BloggingContext())
{
// Create a new blog and save it
db.Blogs.Add(new Blog
{
Name = "Test Blog #" + (db.Blogs.Count() + 1)
});
Console.WriteLine("Calling SaveChanges.");
db.SaveChanges();
Console.WriteLine("SaveChanges completed.");
// Query for all blogs ordered by name
Console.WriteLine("Executing query.");
var blogs = (from b in db.Blogs
orderby b.Name
select b).ToList();
// Write all blogs out to Console
Console.WriteLine("Query completed with following results:");
foreach (var blog in blogs)
{
Console.WriteLine(" " + blog.Name);
}
}
}
}
}
Этот код вызывает PerformDatabaseOperations
метод, который сохраняет новый блог в базе данных, а затем извлекает все блоги из базы данных и выводит их в консоль. После этого программа записывает цитату дня в консоль.
Так как код синхронен, при запуске программы можно наблюдать следующий поток выполнения:
SaveChanges
начинает отправлять новый блог в базу данныхSaveChanges
Завершает- Запрос ко всем блогам отправляется в базу данных
- Возвращаемые запросы и результаты записываются в консоль
- Цитата дня записывается в консоль
Создание асинхронного
Теперь, когда у нас есть программа, мы можем начать использовать новые асинхронные и ожидающие ключевое слово. Мы внесли следующие изменения в Program.cs
- Строка 2. Оператор using для
System.Data.Entity
пространства имен предоставляет нам доступ к методам расширения асинхронного расширения EF. - Строка 4. Оператор using для
System.Threading.Tasks
пространства имен позволяет использоватьTask
тип. - Строка 12 и 18. Мы захватываем как задачу, отслеживающую ход выполнения
PerformSomeDatabaseOperations
(строка 12), а затем блокируем выполнение программы для выполнения этой задачи после завершения всей работы программы (строка 18). - Строка 25. Мы обновили,
PerformSomeDatabaseOperations
чтобы они были помечены какasync
и возвращаютсяTask
. - Строка 35. Теперь мы вызываем асинхронную
SaveChanges
версию и ожидаем его завершения. - Строка 42. Теперь мы вызываем асинхронную
ToList
версию и ожидаем результата.
Полный список доступных методов расширения в System.Data.Entity
пространстве имен см. в QueryableExtensions
классе. Вам также потребуется добавить using System.Data.Entity
в инструкции using.
using System;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
namespace AsyncDemo
{
class Program
{
static void Main(string[] args)
{
var task = PerformDatabaseOperations();
Console.WriteLine("Quote of the day");
Console.WriteLine(" Don't worry about the world coming to an end today... ");
Console.WriteLine(" It's already tomorrow in Australia.");
task.Wait();
Console.WriteLine();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
public static async Task PerformDatabaseOperations()
{
using (var db = new BloggingContext())
{
// Create a new blog and save it
db.Blogs.Add(new Blog
{
Name = "Test Blog #" + (db.Blogs.Count() + 1)
});
Console.WriteLine("Calling SaveChanges.");
await db.SaveChangesAsync();
Console.WriteLine("SaveChanges completed.");
// Query for all blogs ordered by name
Console.WriteLine("Executing query.");
var blogs = await (from b in db.Blogs
orderby b.Name
select b).ToListAsync();
// Write all blogs out to Console
Console.WriteLine("Query completed with following results:");
foreach (var blog in blogs)
{
Console.WriteLine(" - " + blog.Name);
}
}
}
}
}
Теперь, когда код является асинхронным, мы можем наблюдать другой поток выполнения при запуске программы:
SaveChanges
начинает отправлять новый блог в базу данных
После отправки команды в базу данных не требуется больше времени вычислений в текущем управляемом потоке. МетодPerformDatabaseOperations
возвращает (даже если он не завершил выполнение) и поток программы в методе Main продолжается.- Цитата дня записывается в консоль
Так как в методе Main больше нет никаких действий, управляемый поток блокируется при вызовеWait
до завершения операции базы данных. Завершив его, оставшаяся часть будетPerformDatabaseOperations
выполнена. SaveChanges
Завершает- Запрос ко всем блогам отправляется в базу данных
Опять же, управляемый поток может выполнять другие действия во время обработки запроса в базе данных. Так как все остальные выполнение завершено, поток просто остановится на вызове Wait, хотя. - Возвращаемые запросы и результаты записываются в консоль
Вынос
Теперь мы узнали, насколько легко использовать асинхронные методы EF. Хотя преимущества асинхронного асинхронного приложения могут быть не очень очевидными в простом консольном приложении, эти же стратегии могут применяться в ситуациях, когда длительные или сетевые действия могут в противном случае заблокировать приложение или вызвать большое количество потоков, чтобы увеличить объем памяти.