EF Core - Logging
Logging trong Entity Framework Core
Chúng ta thường lưu vết lại SQL và thay đổi thông tin theo dõi cho mục đích gỡ lỗi trong EF Core.
Lưu vết trong EF Core tự động tích hợp với các cơ chế lưu vết của .NET Core. Vì vậy, hãy tìm hiểu về các nguyên tắc cơ bản về lưu vết .NET Core trước khi bắt đầu lưu vết EF Core
Entity Framework Core tích hợp với lưu vết .NET Core để lưu vết SQL và thay đổi thông tin theo dõi cho các mục tiêu đầu ra khác nhau. Đầu tiên, hãy cài đặt gói Nuget dành cho nhà cung cấp dịch vụ lưu vết mà bạn chọn, sau đó liên kết DbContext với ILoggerFactory.
Cài đặt gói NuGet của nhà cung cấp dịch vụ lưu vết. Tại đây, chúng tôi sẽ hiển thị lưu vết trên bảng điều khiển, vì vậy hãy cài đặt gói Microsoft.Extensions.Logging.Console NuGet từ Trình quản lý gói NuGet hoặc thực hiện lệnh sau trong Bảng điều khiển Trình quản lý Gói:
PM> Install-Package Microsoft.Extensions.Logging.Console
Hình sau minh họa cách DbContext hoạt động với API lưu vết và nhà cung cấp lưu vết bảng điều khiển.
Sau khi cài đặt trình cung cấp trình ghi bảng điều khiển, bạn cần tạo một phiên bản static / singleton của LoggerFactory và sau đó buộc nó với một DbContext, như được hiển thị bên dưới.
public class SchoolContext : DbContext
{
//static LoggerFactory object
public static readonly ILoggerFactory loggerFactory = new LoggerFactory(new[] {
new ConsoleLoggerProvider((_, __) => true, true)
});
//or
// public static readonly ILoggerFactory loggerFactory = new LoggerFactory().AddConsole((_,___) => true);
public SchoolContext():base()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLoggerFactory(loggerFactory) //tie-up DbContext with LoggerFactory object
.EnableSensitiveDataLogging()
.UseSqlServer(@"Server=.\SQLEXPRESS;Database=SchoolDB;Trusted_Connection=True;");
}
public DbSet<Student> Students { get; set; }
}
Trong ví dụ trên, chúng ta đã tạo một đối tượng của lớp LoggerFactory và gán nó cho biến tĩnh kiểu ILoggerFactory. Sau đó, chúng ta truyền đối tượng này vào phương thức optionsBuilder.UseLoggerFactory () trong phương thức OnConfiguring (). Điều này sẽ cho phép DbContext chia sẻ thông tin với đối tượng loggerFactory, đối tượng này sẽ hiển thị tất cả thông tin ghi nhật ký trên bảng điều khiển.
Theo mặc định, EF Core sẽ không ghi dữ liệu nhạy cảm, chẳng hạn như giá trị tham số bộ lọc. Vì vậy, hãy gọi EnableSensitiveDataLogging () để ghi dữ liệu nhạy cảm.
Chú ý:
Chúng ta hãy hiểu ví dụ trên một cách chi tiết.
Đầu tiên, chúng tôi tạo một đối tượng của lớp LoggerFactory và gán nó cho biến tĩnh kiểu ILoggerFactory, như hình dưới đây.
public static readonly ILoggerFactory loggerFactory = new LoggerFactory(
new[] { new ConsoleLoggerProvider ((_, __) => true, true) }
);
LoggerFactory có thể chứa một hoặc nhiều nhà cung cấp lưu vết có thể được sử dụng để đăng nhập đồng thời vào nhiều phương tiện. Hàm tạo của LoggerFactory chấp nhận một mảng các đối tượng trình cung cấp trình lưu vết khác nhau là mới [] {}. Chúng tôi muốn hiển thị nhật ký trên bảng điều khiển, vì vậy hãy tạo một đối tượng của nhà cung cấp trình lưu vết bảng điều khiển ConsoleLoggerProvider.
Có bốn hàm tạo của ConsoleLoggerProvider. Sử dụng hàm cho phép biểu thức lambda (Func <>) để lọc nhật ký và bao gồm Scope Boolean, như được hiển thị bên dưới.
new ConsoleLoggerProvider((_, __) => true, true)
Ở đây, chúng ta không muốn lọc bất kỳ thông tin nào để biểu thức lambda luôn trả về true (_, __) => true.
Sau khi tạo một đối tượng của ILoggerFactory, hãy liên kết DbContext với ILoggerFactory trong phương thức OnConfiguring () bằng cách sử dụng DbContextOptionsBuilder.
optionsBuilder.UseLoggerFactory(loggerFactory)
Do đó, chúng ta đã gắn kết DbContext với LoggerFactory bao gồm nhà cung cấp trình ghi bảng điều khiển. Bây giờ, chúng ta có thể xem tất cả nhật ký trên bảng điều khiển bất cứ khi nào một phiên bản của DbContext thực thi bất kỳ hành động nào.
Hãy xem xét ví dụ sau.
using (var context = new SchoolContext())
{
var std = new Student(){ StudentName = "Steve" };
context.Add(std);
context.SaveChanges();
Console.ReadLine();
}
Ví dụ trên sẽ hiển thị các bản ghi sau trên bảng điều khiển:
dbug: Microsoft.EntityFrameworkCore.Infrastructure[100401]
An 'IServiceProvider' was created for internal use by Entity Framework.
info: Microsoft.EntityFrameworkCore.Infrastructure[100403]
Entity Framework Core 2.0.0-rtm-26452 initialized 'SchoolContext' using pr
ovider 'Microsoft.EntityFrameworkCore.SqlServer' with options: SensitiveDataLoggingEnabled
dbug: Microsoft.EntityFrameworkCore.Database.Connection[200000]
Opening connection to database 'SchoolDB' on server '.\SQLEXPRESS'.
dbug: Microsoft.EntityFrameworkCore.Database.Connection[200001]
Opened connection to database 'SchoolDB' on server '.\SQLEXPRESS'.
dbug: Microsoft.EntityFrameworkCore.Database.Transaction[200200]
Beginning transaction with isolation level 'ReadCommitted'.
warn: Microsoft.EntityFrameworkCore.Database.Command[100400]
Sensitive data logging is enabled. Log entries and exception messages may
include sensitive application data, this mode should only be enabled during development.
dbug: Microsoft.EntityFrameworkCore.Database.Command[200100]
Executing DbCommand [Parameters=[@p0='' (DbType = DateTime2), @p1='' (DbTy
pe = Int32), @p2='0', @p3='' (Size = 8000) (DbType = Binary), @p4='Steve' (Size = 4000), @p5='0'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
INSERT INTO [Students] ([DateOfBirth], [GradeId], [Height], [Photo], [Stud
entName], [Weight])
VALUES (@p0, @p1, @p2, @p3, @p4, @p5);
SELECT [StudentID]
FROM [Students]
WHERE @@ROWCOUNT = 1 AND [StudentID] = scope_identity();
info: Microsoft.EntityFrameworkCore.Database.Command[200101]
Executed DbCommand (68ms) [Parameters=[@p0='' (DbType = DateTime2), @p1=''
(DbType = Int32), @p2='0', @p3='' (Size = 8000) (DbType = Binary), @p4='Steve'
(Size = 4000), @p5='0'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
INSERT INTO [Students] ([DateOfBirth], [GradeId], [Height], [Photo], [Stud
entName], [Weight])
VALUES (@p0, @p1, @p2, @p3, @p4, @p5);
SELECT [StudentID]
FROM [Students]
WHERE @@ROWCOUNT = 1 AND [StudentID] = scope_identity();
dbug: Microsoft.EntityFrameworkCore.Database.Command[200300]
A data reader was disposed.
dbug: Microsoft.EntityFrameworkCore.Database.Transaction[200202]
Committing transaction.
dbug: Microsoft.EntityFrameworkCore.Database.Connection[200002]
Closing connection to database 'SchoolDB' on server '.\SQLEXPRESS'.
dbug: Microsoft.EntityFrameworkCore.Database.Connection[200003]
Closed connection to database 'SchoolDB' on server '.\SQLEXPRESS'.
dbug: Microsoft.EntityFrameworkCore.Database.Transaction[200204]
Disposing transaction.
Filter Logs
Trong ví dụ trên, DbContext đã ghi lại tất cả thông tin trong khi lưu một thực thể. Đôi khi bạn không muốn ghi lại tất cả thông tin và lọc một số nhật ký không mong muốn. Trong EF Core, bạn có thể lọc nhật ký bằng cách chỉ định danh mục trình lưu vết và cấp độ nhật ký.
Logger Categories
EF Core 2.x bao gồm lớp DbLoggerCategory để có được một danh mục Entity Framework Core logger bằng cách sử dụng thuộc tính Name của nó. Bảng sau liệt kê các danh mục trình lưu vết khác nhau.
Logger Category Class | Description |
---|---|
Database.Command | Logger category for command execution, including SQL sent to database. |
Database.Connection | Logger category for db connection operations. |
Database.Transaction | Logger category for db transactions. |
Infrastructure | Logger category for miscellaneous messages for the EF infrastructure. |
Migration | Logger category for migrations. |
Model | Logger category for model building and metadata. |
Query | Logger category for queries (excluding generated SQL). |
Scaffolding | Logger category for scaffolding and reverse engineering. |
Update | Logger category for DbContext.SaveChanges() messages. |
Lưu vết các truy vấn SQL
Để lưu vết các truy vấn SQL, hãy khai báo danh mục DbLoggerCategory.Database.Command và LogLevel.Information trong biểu thức lambda trong hàm tạo của ConsoleLoggerProvider, như được hiển thị bên dưới.
public static readonly ILoggerFactory consoleLoggerFactory
= new LoggerFactory(new[] {
new ConsoleLoggerProvider((category, level) =>
category == DbLoggerCategory.Database.Command.Name &&
level == LogLevel.Information, true)
});
Hoặc, chỉ cần gọi phương thức AddConsole () trên LoggerFactory để ghi các truy vấn SQL, theo mặc định.
public static readonly ILoggerFactory consoleLoggerFactory
= new LoggerFactory().AddConsole();
Bây giờ, điều này sẽ lưu vết thông tin truy vấn sau đây để lưu một thực thể bằng DbContext.
info: Microsoft.EntityFrameworkCore.Database.Command[200101]
Executed DbCommand (73ms) [Parameters=[@p0='' (DbType = DateTime2), @p1=''
(DbType = Int32), @p2='0', @p3='' (Size = 8000) (DbType = Binary), @p4='Steve'
(Size = 4000), @p5='0'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
INSERT INTO [Students] ([DateOfBirth], [GradeId], [Height], [Photo], [Stud
entName], [Weight])
VALUES (@p0, @p1, @p2, @p3, @p4, @p5);
SELECT [StudentID]
FROM [Students]
WHERE @@ROWCOUNT = 1 AND [StudentID] = scope_identity();