کلاس SearchApartmentsQueryHandler
این کلاس مسئول پردازش درخواستهای جستجوی آپارتمانها است. این کلاس از الگوی CQRS پیروی میکند و به عنوان یک Query Handler عمل میکند.
ویژگیهای کلیدی
پردازش جستجوی آپارتمانها:
- مدیریت تراکنشها و ذخیرهسازی
- استفاده از الگوی Query Handler برای جداسازی مسئولیتها
Dependency Injection:
- استفاده از DI برای مدیریت وابستگیها
- افزایش تستپذیری و انعطافپذیری
ساختار کد
csharp
internal sealed class SearchApartmentsQueryHandler : IQueryHandler<SearchApartmentsQuery, IReadOnlyList<ApartmentResponse>>
{
private readonly ISqlConnectionFactory _sqlConnectionFactory;
private static readonly int[] ActiveBookingStatuses =
[
(int)BookingStatus.Reserved,
(int)BookingStatus.Confirmed,
(int)BookingStatus.Completed,
];
public SearchApartmentsQueryHandler(ISqlConnectionFactory sqlConnectionFactory)
{
_sqlConnectionFactory = sqlConnectionFactory;
}
public async Task<Result<IReadOnlyList<ApartmentResponse>>> Handle(SearchApartmentsQuery request, CancellationToken cancellationToken)
{
if(request.StartDate > request.EndDate)
{
return new List<ApartmentResponse>();
}
using var connection = _sqlConnectionFactory.CreateConnection();
var sql = """
SELECT
a.id AS Id,
a.name AS Name,
a.description AS Description,
a.price_amount AS Price,
a.price_currency AS Currency,
a.address_country AS Country,
a.address_state AS State,
a.address_zip_code AS ZipCode,
a.address_city AS City,
a.address_street AS Street
FROM apartments AS a
WHERE NOT EXISTS
(
SELECT 1
FROM bookings AS b
WHERE
b.apartment_id = a.id AND
b.duration_start <= @EndDate AND
b.duration_end >= @StartDate AND
b.status = ANY(@ActiveBookingStatuses)
)
""";
var apartments = await connection.QueryAsync<ApartmentResponse, AddressResponse, ApartmentResponse>(sql,
(apartment, address) =>
{
apartment.Address = address;
return apartment;
},
new
{
request.StartDate,
request.EndDate,
ActiveBookingStatuses
},
splitOn: "Country");
return apartments.ToList();
}
}
نحوه کار
دریافت درخواست:
- دریافت اطلاعات جستجوی آپارتمانها
- اعتبارسنجی اولیه دادهها توسط Validator
پردازش درخواست:
- بررسی وجود آپارتمانها
- جستجوی آپارتمانها و مدیریت تراکنشها
ذخیرهسازی:
- ذخیره تغییرات با استفاده از UnitOfWork
- بازگرداندن نتیجه در صورت موفقیت
مزایای این طراحی
جداسازی مسئولیتها:
- هر کلاس تنها یک وظیفه مشخص دارد
- رعایت اصل Single Responsibility
قابلیت تستپذیری بالا:
- امکان mock کردن وابستگیها
- تستهای مجزا برای هر بخش
مدیریت خطا:
- استفاده از الگوی Result برای مدیریت خطاها
- بازگشت پیامهای خطای معنادار