Kueri asinkron dan simpan
Catatan
Hanya EF6 dan seterusnya - Fitur, API, dll. yang dibahas di halaman ini dimasukkan dalam Entity Framework 6. Jika Anda menggunakan versi yang lebih lama, beberapa atau semua informasi tidak berlaku.
EF6 memperkenalkan dukungan untuk kueri asinkron dan menyimpan menggunakan asinkron dan menunggu kata kunci yang diperkenalkan di .NET 4.5. Meskipun tidak semua aplikasi dapat memperoleh manfaat dari asinkron, aplikasi dapat digunakan untuk meningkatkan respons klien dan skalabilitas server saat menangani tugas yang berjalan lama, jaringan, atau terikat I/O.
Kapan benar-benar menggunakan asinkron
Tujuan dari panduan ini adalah untuk memperkenalkan konsep asinkron dengan cara yang memudahkan untuk mengamati perbedaan antara eksekusi program asinkron dan sinkron. Panduan ini tidak dimaksudkan untuk mengilustrasikan salah satu skenario utama di mana pemrograman asinkron memberikan manfaat.
Pemrograman asinkron terutama difokuskan untuk membebaskan utas terkelola saat ini (utas yang menjalankan kode .NET) untuk melakukan pekerjaan lain saat menunggu operasi yang tidak memerlukan waktu komputasi dari utas terkelola. Misalnya, sementara mesin database memproses kueri tidak ada yang harus dilakukan oleh kode .NET.
Dalam aplikasi klien (WinForms, WPF, dll.) utas saat ini dapat digunakan untuk menjaga UI tetap responsif saat operasi asinkron dilakukan. Dalam aplikasi server (ASP.NET dll.) utas dapat digunakan untuk memproses permintaan masuk lainnya - ini dapat mengurangi penggunaan memori dan/atau meningkatkan throughput server.
Di sebagian besar aplikasi yang menggunakan asinkron tidak akan memiliki manfaat yang nyata dan bahkan bisa merugikan. Gunakan pengujian, pembuatan profil, dan akal sehat untuk mengukur dampak asinkron dalam skenario khusus Anda sebelum berkomitmen padanya.
Berikut adalah beberapa sumber daya lainnya untuk dipelajari tentang asinkron:
- Gambaran umum Brandon Bray tentang asinkron/tunggu di .NET 4.5
- Halaman Pemrograman Asinkron di Pustaka MSDN
Membuat model
Kami akan menggunakan alur kerja Code First untuk membuat model kami dan menghasilkan database, namun fungsionalitas asinkron akan berfungsi dengan semua model EF termasuk yang dibuat dengan Desainer EF.
- Buat Aplikasi Konsol dan sebut saja AsyncDemo
- Menambahkan paket EntityFramework NuGet
- Di Penjelajah Solusi, klik kanan pada proyek AsyncDemo
- Pilih Kelola Paket NuGet...
- Dalam dialog Kelola Paket NuGet, Pilih tab Online dan pilih paket EntityFramework
- Klik Instal
- Tambahkan kelas Model.cs dengan implementasi berikut
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; }
}
}
Membuat program sinkron
Sekarang setelah kita memiliki model EF, mari kita tulis beberapa kode yang menggunakannya untuk melakukan beberapa akses data.
- Ganti konten Program.cs dengan kode berikut
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);
}
}
}
}
}
Kode ini memanggil PerformDatabaseOperations
metode yang menyimpan Blog baru ke database dan kemudian mengambil semua Blog dari database dan mencetaknya ke Konsol. Setelah ini, program menulis kutipan hari ke Konsol.
Karena kodenya sinkron, kita dapat mengamati alur eksekusi berikut ketika kita menjalankan program:
SaveChanges
mulai mendorong Blog baru ke databaseSaveChanges
Selesai- Kueri untuk semua Blog dikirim ke database
- Pengembalian kueri dan hasil ditulis ke Konsol
- Kutipan hari ditulis ke Konsol
Membuatnya asinkron
Sekarang setelah program kita berjalan, kita dapat mulai menggunakan asinkron baru dan menunggu kata kunci. Kami telah membuat perubahan berikut pada Program.cs
- Baris 2: Pernyataan penggunaan untuk
System.Data.Entity
namespace memberi kami akses ke metode ekstensi asinkron EF. - Baris 4: Pernyataan penggunaan untuk
System.Threading.Tasks
namespace memungkinkan kita untuk menggunakan jenis .Task
- Baris 12 & 18: Kami menangkap sebagai tugas yang memantau kemajuan
PerformSomeDatabaseOperations
(baris 12) dan kemudian memblokir eksekusi program agar tugas ini selesai setelah semua pekerjaan untuk program selesai (baris 18). - Baris 25: Kami telah memperbarui
PerformSomeDatabaseOperations
untuk ditandai sebagaiasync
dan mengembalikanTask
. - Baris 35: Kami sekarang memanggil versi
SaveChanges
Asinkron dan menunggu penyelesaiannya. - Baris 42: Kami sekarang memanggil versi
ToList
Asinkron dan menunggu hasilnya.
Untuk daftar komprehensif metode ekstensi yang tersedia di System.Data.Entity
namespace layanan, lihat QueryableExtensions
kelas . Anda juga perlu menambahkan using System.Data.Entity
ke pernyataan penggunaan Anda.
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);
}
}
}
}
}
Sekarang setelah kode asinkron, kita dapat mengamati alur eksekusi yang berbeda ketika kita menjalankan program:
SaveChanges
mulai mendorong Blog baru ke database
Setelah perintah dikirim ke database, tidak ada lagi waktu komputasi yang diperlukan pada utas terkelola saat ini. MetodePerformDatabaseOperations
mengembalikan (meskipun belum selesai dieksekusi) dan alur program dalam metode Utama berlanjut.- Kutipan hari ditulis ke Konsol
Karena tidak ada lagi pekerjaan yang harus dilakukan dalam metode Utama, utas terkelola diblokir padaWait
panggilan hingga operasi database selesai. Setelah selesai, sisa dari kitaPerformDatabaseOperations
akan dieksekusi. SaveChanges
Selesai- Kueri untuk semua Blog dikirim ke database
Sekali lagi, utas terkelola bebas untuk melakukan pekerjaan lain saat kueri diproses dalam database. Karena semua eksekusi lainnya telah selesai, utas hanya akan berhenti pada panggilan Tunggu sekalipun. - Pengembalian kueri dan hasil ditulis ke Konsol
Takeaway
Kami sekarang melihat betapa mudahnya menggunakan metode asinkron EF. Meskipun keuntungan asinkron mungkin tidak terlalu jelas dengan aplikasi konsol sederhana, strategi yang sama ini dapat diterapkan dalam situasi di mana aktivitas jangka panjang atau terikat jaringan mungkin memblokir aplikasi, atau menyebabkan sejumlah besar utas meningkatkan jejak memori.