Menggunakan Listener Diagnostik di EF Core
Tip
Anda dapat mengunduh sampel artikel ini dari GitHub.
Pendengar diagnostik memungkinkan mendengarkan peristiwa EF Core apa pun yang terjadi di dalam proses .NET saat ini. Kelas DiagnosticListener adalah bagian dari mekanisme umum di seluruh .NET untuk mendapatkan informasi diagnostik dari menjalankan aplikasi.
Pendengar diagnostik tidak sesuai untuk mendapatkan peristiwa hanya dari satu instans DbContext. Pencegat EF Core menyediakan akses ke peristiwa yang sama dengan pendaftaran per konteks.
Pendengar diagnostik tidak dirancang untuk melakukan pengelogan. Pertimbangkan untuk menggunakan pengelogan sederhana atau Microsoft.Extensions.Logging untuk pengelogan.
Contoh: Mengamati peristiwa diagnostik
Menyelesaikan peristiwa EF Core adalah proses dua langkah. Pertama, pengamat untuk DiagnosticListener
dirinya sendiri harus dibuat:
public class DiagnosticObserver : IObserver<DiagnosticListener>
{
public void OnCompleted()
=> throw new NotImplementedException();
public void OnError(Exception error)
=> throw new NotImplementedException();
public void OnNext(DiagnosticListener value)
{
if (value.Name == DbLoggerCategory.Name) // "Microsoft.EntityFrameworkCore"
{
value.Subscribe(new KeyValueObserver());
}
}
}
Metode OnNext
ini mencari DiagnosticListener yang berasal dari EF Core. Pendengar ini memiliki nama "Microsoft.EntityFrameworkCore", yang dapat diperoleh dari kelas seperti yang ditunjukkan DbLoggerCategory .
Pengamat ini kemudian harus terdaftar secara global, misalnya dalam metode aplikasi Main
:
DiagnosticListener.AllListeners.Subscribe(new DiagnosticObserver());
Kedua, setelah EF Core DiagnosticListener ditemukan, pengamat nilai kunci baru dibuat untuk berlangganan peristiwa EF Core yang sebenarnya. Contohnya:
public class KeyValueObserver : IObserver<KeyValuePair<string, object>>
{
public void OnCompleted()
=> throw new NotImplementedException();
public void OnError(Exception error)
=> throw new NotImplementedException();
public void OnNext(KeyValuePair<string, object> value)
{
if (value.Key == CoreEventId.ContextInitialized.Name)
{
var payload = (ContextInitializedEventData)value.Value;
Console.WriteLine($"EF is initializing {payload.Context.GetType().Name} ");
}
if (value.Key == RelationalEventId.ConnectionOpening.Name)
{
var payload = (ConnectionEventData)value.Value;
Console.WriteLine($"EF is opening a connection to {payload.Connection.ConnectionString} ");
}
}
}
Metode OnNext
ini kali ini dipanggil dengan pasangan kunci/nilai untuk setiap peristiwa EF Core. Kuncinya adalah nama peristiwa, yang dapat diperoleh dari salah satu dari:
- CoreEventId untuk peristiwa yang umum untuk semua penyedia database EF Core
- RelationalEventId untuk peristiwa yang umum untuk semua penyedia database relasional
- Kelas serupa untuk peristiwa khusus untuk penyedia database saat ini. Misalnya, SqlServerEventId untuk penyedia SQL Server.
Nilai pasangan kunci/nilai adalah jenis payload khusus untuk peristiwa tersebut. Jenis payload yang diharapkan didokumentasikan pada setiap peristiwa yang ditentukan dalam kelas peristiwa ini.
Misalnya, kode di atas menangani ContextInitialized dan ConnectionOpening peristiwa. Untuk yang pertama, payload adalah ContextInitializedEventData. Untuk yang kedua, itu adalah ConnectionEventData.
Tip
ToString ditimpa di setiap kelas data peristiwa EF Core untuk menghasilkan pesan log yang setara untuk peristiwa tersebut. Misalnya, panggilan ContextInitializedEventData.ToString
menghasilkan "Entity Framework Core 5.0.0 inisialisasi 'BlogsContext' menggunakan penyedia 'Microsoft.EntityFrameworkCore.Sqlite' dengan opsi: None".
Sampel berisi aplikasi konsol sederhana yang membuat perubahan pada database blogging dan mencetak peristiwa diagnostik yang ditemui.
public static void Main()
{
DiagnosticListener.AllListeners.Subscribe(new DiagnosticObserver());
using (var context = new BlogsContext())
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
context.Add(
new Blog { Name = "EF Blog", Posts = { new Post { Title = "EF Core 3.1!" }, new Post { Title = "EF Core 5.0!" } } });
context.SaveChanges();
}
using (var context = new BlogsContext())
{
var blog = context.Blogs.Include(e => e.Posts).Single();
blog.Name = "EF Core Blog";
context.Remove(blog.Posts.First());
blog.Posts.Add(new Post { Title = "EF Core 6.0!" });
context.SaveChanges();
}
Output dari kode ini menunjukkan peristiwa yang terdeteksi:
EF is initializing BlogsContext
EF is opening a connection to Data Source=blogs.db;Mode=ReadOnly
EF is opening a connection to DataSource=blogs.db
EF is opening a connection to Data Source=blogs.db;Mode=ReadOnly
EF is opening a connection to DataSource=blogs.db
EF is opening a connection to DataSource=blogs.db
EF is opening a connection to DataSource=blogs.db
EF is initializing BlogsContext
EF is opening a connection to DataSource=blogs.db
EF is opening a connection to DataSource=blogs.db
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk