AutoMapper — DTO ↔ Entity mapping, Profile, ProjectTo
Muammodan boshlaylik
DTO lar kerak (45-dars) — lekin har bir entity uchun qo'lda nusxalash:
var dto = new MahsulotDto
{
Id = m.Id,
Nomi = m.Nomi,
Narx = m.Narx,
Tavsif = m.Tavsif,
Qoldiq = m.Qoldiq,
KategoriyaNomi = m.Kategoriya.Nomi,
// ... yana 12 ta maydon
};
Bu kod 5 ta joyda takrorlanadi. Entity ga yangi maydon qo'shilsa — hamma joyni topib yangilash kerak; bitta joyda unutilsa — API bo'sh qiymat qaytaradi.
AutoMapper nima?
AutoMapper — ob'ektlarni nomlar bo'yicha avtomatik nusxalaydigan kutubxona. Bir xil nomdagi xususiyatlar o'zi ko'chiriladi, farqlilari — bir marta sozlanadi.
dotnet add package AutoMapper
[!INFO] AutoMapper 15-versiyadan boshlab tijoriy litsenziyaga o'tgan (kichik kompaniyalar va notijorat loyihalar uchun bepul "Community" litsenziya bor, kalit talab qilinadi). Eski 14.x versiyasi MIT litsenziyasida qoladi. Loyihaga qo'shishdan oldin litsenziya shartlarini tekshiring — shuning uchun quyida muqobillar ham ko'rsatilgan.
Hayotiy o'xshatma
Ko'chish paytidagi yuk tashuvchilar. Siz har bir buyumni qaysi xonaga qo'yishni alohida aytmaysiz — qutilarda "oshxona", "yotoqxona" deb yozilgan, va ular bir xil nomli xonaga qo'yiladi. Faqat istisnolarni aytasiz: "katta ko'zgu — mehmonxonaga emas, dahlizga".
Profil — sozlamalar
using AutoMapper;
public class MahsulotProfili : Profile
{
public MahsulotProfili()
{
// Entity → DTO
CreateMap<Mahsulot, MahsulotDto>()
.ForMember(d => d.KategoriyaNomi, o => o.MapFrom(s => s.Kategoriya.Nomi))
.ForMember(d => d.Mavjud, o => o.MapFrom(s => s.Qoldiq > 0));
// DTO → Entity
CreateMap<MahsulotYaratDto, Mahsulot>()
.ForMember(d => d.Id, o => o.Ignore())
.ForMember(d => d.Yaratilgan, o => o.Ignore());
}
}
Flattening — KategoriyaNomi nomi Kategoriya.Nomi ga mos keladi, shuning uchun aslida ForMember siz ham avtomatik ishlaydi.
Ro'yxatdan o'tkazish
builder.Services.AddAutoMapper(cfg => { }, typeof(MahsulotProfili));
Berilgan assembly dagi barcha Profile klasslari topiladi.
Ishlatish
public class MahsulotService(DokonDbContext db, IMapper mapper)
{
public async Task<MahsulotDto?> OlAsync(int id, CancellationToken ct)
{
var m = await db.Mahsulotlar.Include(x => x.Kategoriya).FirstOrDefaultAsync(x => x.Id == id, ct);
return m is null ? null : mapper.Map<MahsulotDto>(m);
}
public async Task<MahsulotDto> YaratAsync(MahsulotYaratDto dto, CancellationToken ct)
{
var m = mapper.Map<Mahsulot>(dto);
db.Mahsulotlar.Add(m);
await db.SaveChangesAsync(ct);
return mapper.Map<MahsulotDto>(m);
}
public async Task YangilaAsync(int id, MahsulotYangilaDto dto, CancellationToken ct)
{
var m = await db.Mahsulotlar.FindAsync([id], ct) ?? throw new TopilmadiException(id);
mapper.Map(dto, m); // mavjud ob'ektga nusxalash
await db.SaveChangesAsync(ct);
}
}
ProjectTo — so'rov darajasida
using AutoMapper.QueryableExtensions;
var royxat = await db.Mahsulotlar
.ProjectTo<MahsulotDto>(mapper.ConfigurationProvider)
.ToListAsync(ct);
ProjectTo mapping ni Select ga aylantiradi — bazadan faqat kerakli ustunlar olinadi, Include shart emas (53-dars, projection).
Konfiguratsiyani tekshirish
[Fact]
public void AutoMapper_konfiguratsiyasi_togri()
{
var config = new MapperConfiguration(c => c.AddProfile<MahsulotProfili>(), NullLoggerFactory.Instance);
config.AssertConfigurationIsValid(); // mos kelmagan maydon bo'lsa — xato
}
Bu test DTO ga yangi maydon qo'shilib, mapping unutilganini darhol ko'rsatadi.
Muqobillar
Qo'lda — kengaytma metodlar
public static class MahsulotMapping
{
public static MahsulotDto ToDto(this Mahsulot m) =>
new(m.Id, m.Nomi, m.Narx, m.Kategoriya.Nomi, m.Qoldiq > 0);
}
var dto = m.ToDto();
Oddiy, tez, kompilyator tekshiradi, "sehr" yo'q. Kichik va o'rta loyihalar uchun ko'pincha eng yaxshi tanlov.
Mapperly — source generator
dotnet add package Riok.Mapperly
[Mapper]
public partial class MahsulotMapper
{
public partial MahsulotDto ToDto(Mahsulot m);
}
Mapping kodi kompilyatsiya vaqtida generatsiya qilinadi — reflection yo'q, qo'lda yozilgandek tez; mos kelmagan maydonlar — kompilyator ogohlantirishi.
| AutoMapper | Qo'lda | Mapperly | |
|---|---|---|---|
| Kod hajmi | Kam | Ko'p | Kam |
| Xatolar aniqlanishi | Runtime / test | Kompilyatsiya | Kompilyatsiya |
| Tezlik | Reflection/expression | Eng tez | Eng tez |
| Debug | Qiyinroq | Oson | Oson (generatsiya qilingan kod) |
| Litsenziya | v15+ tijoriy | — | MIT |
[!TIP] Yangi loyihada: oddiy holatlarda — qo'lda yozilgan
ToDto()kengaytmalari; ko'p DTO li katta loyihada — Mapperly. AutoMapper — u allaqachon ishlatilgan loyihalarda vaProjectToqulayligi juda kerak bo'lganda.
Tez-tez uchraydigan xatolar
Mapping ichida biznes mantiq (MapFrom(s => s.Narx * kurs.Ol())) — yashirin, test qilish qiyin; mapping faqat nusxalash uchun.
DTO → Entity da Id yoki maxfiy maydonlar ustidan yozish — Ignore() yoki alohida yaratish DTO si.
Include siz Map — navigatsiya null, NullReferenceException; yoki ProjectTo.
Xulosa
AutoMapper — nomlar bo'yicha avtomatik nusxalash: Profile da CreateMap<Manba, Maqsad>(), farqlilar — ForMember(... MapFrom ...), keraksizlar — Ignore(). AddAutoMapper, IMapper.Map<T>(), mavjud ob'ektga Map(dto, entity); ProjectTo — so'rov darajasida faqat kerakli ustunlar. AssertConfigurationIsValid — testda.
v15+ tijoriy litsenziya. Muqobillar: qo'lda ToDto() kengaytmalari (oddiy, kompilyator tekshiradi) va Mapperly (source generator, tez). Mapping da biznes mantiq bo'lmasin.
Keyingi dars
65-dars: Global Exception Handling — IExceptionHandler, ProblemDetails