โอเคครับ 😎 มาลุย ICommand<Guid>
แบบละเอียดยิบใน C# / .NET Core สไตล์ CQRS กัน
1️⃣ พื้นฐาน ICommand<T>
โดยทั่วไปใน CQRS (Command Query Responsibility Segregation) เราจะแบ่งออกเป็น 2 ส่วน:
ส่วน | ความหมาย |
---|---|
Query | อ่านข้อมูล (Read) |
Command | เขียน/แก้ไขข้อมูล (Write) |
ICommand<T>
คือ interface สำหรับ Command ที่ระบุว่า:
“เมื่อรัน Command นี้แล้ว จะคืนค่า
T
”
-
T
มักเป็น ผลลัพธ์ของการสร้าง/แก้ไข เช่นGuid
ของ entity ที่สร้างใหม่ หรือbool
สำหรับสถานะสำเร็จ/ล้มเหลว
2️⃣ ตัวอย่าง ICommand<Guid>
public interface ICommand<TResult>
{
// Marker interface หรือใส่ property/metadata ที่จำเป็นสำหรับ Command
}
สมมติเราต้องการสร้าง Log ใหม่:
public class CreateAppLogCommand : ICommand<Guid>
{
public string Message { get; set; } = string.Empty;
public string Level { get; set; } = "Info"; // Info, Warning, Error
}
-
ICommand<Guid>
→ บอกว่า ผลลัพธ์ของการรัน command นี้คือ Guid -
Guid อาจเป็น ID ของ log ใหม่ ที่ถูกสร้างใน DB
3️⃣ Command Handler: ICommandHandler<TCommand, TResult>
เพื่อทำงานกับ command เราจะใช้ handler:
public interface ICommandHandler<TCommand, TResult>
where TCommand : ICommand<TResult>
{
Task<TResult> HandleAsync(TCommand command);
}
-
รับ
TCommand
→ ทำ action → returnTResult
4️⃣ ตัวอย่าง Command Handler: สร้าง log
public class CreateAppLogCommandHandler : ICommandHandler<CreateAppLogCommand, Guid>
{
private readonly AppDbContext _dbContext;
public CreateAppLogCommandHandler(AppDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<Guid> HandleAsync(CreateAppLogCommand command)
{
var entity = new AppLog
{
Id = Guid.NewGuid(),
Message = command.Message,
Level = command.Level,
CreatedAt = DateTime.UtcNow
};
_dbContext.AppLogs.Add(entity);
await _dbContext.SaveChangesAsync();
// คืนค่า ID ของ log ที่สร้างใหม่
return entity.Id;
}
}
อธิบายทีละขั้น:
-
ICommandHandler<CreateAppLogCommand, Guid>
→ คืนค่าGuid
ของ entity ใหม่ -
HandleAsync
→ method ทำงานจริงกับ DB -
สร้าง entity ใหม่ map จาก command
-
save ลง DB
-
return
Guid
ของ log ใหม่
5️⃣ วิธีเรียกใช้งาน
var command = new CreateAppLogCommand
{
Message = "Something happened",
Level = "Error"
};
Guid newLogId = await _commandBus.SendAsync(command);
Console.WriteLine($"New log created with ID: {newLogId}");
-
Command bus / mediator จะส่ง command ไปหา handler ที่ตรงกัน
-
คืนค่า
Guid
ของ entity ใหม่
6️⃣ สรุป Concept
สิ่งที่ทำ | ความหมาย |
---|---|
ICommand<Guid> |
Command ที่เมื่อรันแล้วคืนค่า Guid |
CreateAppLogCommand |
Command สำหรับสร้าง log ใหม่ |
CreateAppLogCommandHandler |
Handler ทำงานจริงกับ DB |
HandleAsync |
สร้าง entity, save DB, return Guid |
CQRS Pattern | แยก Read / Write → maintainable, testable |
💡 Tip:
-
ถ้า command ไม่ต้อง return อะไร → ใช้
ICommand<Unit>
หรือTask
-
Command handler ไม่ควร query หรือ return ข้อมูลอื่น ๆ มากเกินไป → ทำงานแค่ write / mutate
ถ้าคุณอยาก ผมสามารถ วาด diagram flowของ ICommand ตั้งแต่ Controller → Command → Handler → DB → return Guid ให้เห็นภาพชัด ๆ แบบ step by step ให้เลยครับ
คุณอยากให้ผมวาด diagram ให้ไหม?