โอเคครับ 😎 เรามาไล่ตั้งแต่ พื้นฐานจนถึงการใช้งาน IQuery<AppLogDto>
ในสไตล์ C# / .NET Core กันเลย
1️⃣ IQuery<T>
คืออะไร?
โดยทั่วไป IQuery<T>
มักจะถูกใช้ใน CQRS (Command Query Responsibility Segregation) pattern
-
Query → ใช้สำหรับ อ่านข้อมูล (Read)
-
Command → ใช้สำหรับ เขียน/แก้ไขข้อมูล (Write)
IQuery<T>
มักถูกออกแบบเป็น interface ที่ระบุว่า “Query นี้จะคืนค่าเป็น T
”
ตัวอย่างโครงสร้างง่าย ๆ:
public interface IQuery<T>
{
// อาจจะมี property สำหรับ filter หรือ paging
}
แล้วเวลาเรียกใช้ เราจะมี Query Handler มาทำงานกับ Query นี้:
public interface IQueryHandler<TQuery, TResult>
where TQuery : IQuery<TResult>
{
Task<TResult> HandleAsync(TQuery query);
}
2️⃣ AppLogDto
คืออะไร?
AppLogDto
คือ Data Transfer Object (DTO) สำหรับเก็บข้อมูล log ของแอป
ตัวอย่าง:
public class AppLogDto
{
public int Id { get; set; }
public string Message { get; set; }
public string Level { get; set; } // Info, Error, Warning
public DateTime CreatedAt { get; set; }
}
3️⃣ สร้าง Query ที่คืน AppLogDto
ตัวอย่าง: Query สำหรับดึง log ทั้งหมด:
public class GetAppLogsQuery : IQuery<IEnumerable<AppLogDto>>
{
public string? Level { get; set; } // filter log level เช่น "Error"
public DateTime? From { get; set; }
public DateTime? To { get; set; }
}
-
IQuery<IEnumerable<AppLogDto>>
→ หมายความว่า query นี้ คืนค่าเป็นลิสต์ของ AppLogDto
4️⃣ Query Handler
public class GetAppLogsQueryHandler : IQueryHandler<GetAppLogsQuery, IEnumerable<AppLogDto>>
{
private readonly AppDbContext _dbContext;
public GetAppLogsQueryHandler(AppDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<IEnumerable<AppLogDto>> HandleAsync(GetAppLogsQuery query)
{
var logs = _dbContext.AppLogs.AsQueryable();
if (!string.IsNullOrEmpty(query.Level))
logs = logs.Where(x => x.Level == query.Level);
if (query.From.HasValue)
logs = logs.Where(x => x.CreatedAt >= query.From.Value);
if (query.To.HasValue)
logs = logs.Where(x => x.CreatedAt <= query.To.Value);
return await logs
.Select(x => new AppLogDto
{
Id = x.Id,
Message = x.Message,
Level = x.Level,
CreatedAt = x.CreatedAt
})
.ToListAsync();
}
}
-
HandleAsync
จะทำ filter, map เป็น DTO และ return -
เราใช้
IQueryable
+ LINQ เพื่อ query database
5️⃣ วิธีเรียกใช้งาน
สมมติมี Query Bus / Mediator:
var query = new GetAppLogsQuery
{
Level = "Error",
From = DateTime.UtcNow.AddDays(-7)
};
var logs = await _queryBus.SendAsync(query);
foreach (var log in logs)
{
Console.WriteLine($"{log.CreatedAt} [{log.Level}] {log.Message}");
}
🔹 สรุป
สิ่งที่ทำ | ความหมาย |
---|---|
IQuery<T> |
Interface สำหรับ query/read คืนค่า T |
AppLogDto |
DTO เก็บข้อมูล log |
IQueryHandler<TQuery, TResult> |
Handle query และ return TResult |
GetAppLogsQuery |
ตัว query ที่ implement IQuery<IEnumerable<AppLogDto>> |
HandleAsync |
ฟังก์ชันทำงานจริง query DB และ return DTO |
💡 เคล็ดลับ:
-
CQRS pattern จะช่วยแยก Read กับ Write ออกจากกัน
-
IQuery<T>
+IQueryHandler<TQuery, TResult>
ทำให้ โค้ดอ่านง่าย ทดสอบง่าย และ maintainable
ถ้าคุณอยาก ผมสามารถ วาด diagram flow ของ IQuery ให้เห็นภาพตั้งแต่ Controller → Query → Handler → DB → DTO เลย ทำให้เข้าใจ CQRS แบบชัดเจนมากขึ้น
คุณอยากให้ผมทำ diagram นั้นไหมครับ?