استفاده از AutoMapper در MVC
شنبه 15 آذر 1393در این مقاله سعی داریم تا مفهوم جدیدی تحت عنوان AutoMapper را در MVC به شما معرفی کنیم.AutoMapper زمانی استفاده می شود که بخواهیم پیچیدگی بایند کردن مدل و ارتباط با entity ها را کاهش دهیم.
زمانی که ما برای یک محیط واقعی کد می زنیم، کارهای بسیاری میکنیم تا کدمان قابل فهم تر باشد و bug های موجود در آن را بهتر بتوان شناسایی و رفع کرد.عمدتا روی این امر تمرکز میکنیم که کد مان قابلیت استفاده مجدد را داشته باشد و تا جای ممکن سعی میکنیم تا هر کدی را که می توانیم تا جای ممکن در متدهای متداول و مورد استفاده خود بگذاریم تا با این کار، هم در زمان برنامه نویس صرفه جویی شود و هم هزینه های پشتیبانی کاهش یابد.
در این مقاله سعی داریم تا مفهوم جدیدی تحت عنوان AutoMapper را در MVC به شما معرفی کنیم.AutoMapper
زمانی استفاده می شود که بخواهیم پیچیدگی بایند کردن مدل و ارتباط با entity ها را کاهش دهیم.
مشکل واقعی:
ما معمولا ارتباط زیادی با entity های database مان و بایند کردن مدلمان با آنها داریم.چیزی که در نهایت ما با آن سرکار داریم چنین چیزی است:
public UserDto GetUserById(string id) { var userDto = new UserDto(); using(var context = new EntityDBContext()) { var user = context.Users.Where(ID => ID.user_id == id).FirstOrDefault(); if (user != null) { userDto.UserId = user.user_id; userDto.Name = user.user_name; userDto.Address = user.user_address; userDto.PhoneNo = user.user_phoneNo; userDto.City = user.user_city; } } return userDto; }
در اینجا میبینیم که پنج property در هر کلاس داریم. و کاری که باید انجام دهیم این است که محتوای db را به مدل خود بایند کنیم و سپس آن را به View پاس دهیم، در این مرحله این کار خیلی ساده به نظر می رسد.
مشکل اصلی وقتی به وجود می آید که ما 25-30 فیلد در رکورد داشته باشیم و بخواهیم این بایند کردن کد را برای همه آن ها در پروژه تکرار کنیم. Copy ، Paste حتی وقتی فقط 5 property داریم.خیلی سخت و رنج آور است.
پیچیدگی بیشتر وقتی به وجود می آید که برای هر View یک ViewModel جداگانه داشته باشیم.در این صورت کار شما دوچندان می شود،اول باید مدل خود را بایند کنید و سپس باید دوباره آن را به viewmodel بایند کنید.
برای گذر از این وضعیت خسته کننده AutoMapper ایجاد شد.
درباره AutoMapper
AutoMapper یک کتابخانه open source است که توسط GitHub ایجاد شده است.CodePlex درمورد AutoMapper این طور میگوید: "AutoMapper یک object-object mapper است. Object-object mapping اینطور کار میکند که object ورودی از یک Type را به object خروجی از type دیگری تبدیل می کند.چیزی که AutoMapper را جذاب میکند این است که AutoMapper قواعدی را فراهم کرده است تا بفهمیم چگونه type A را بهtype B ، Map کنیم.تا زمانیکه type B ، از قواعد AutoMapper پیروی میکند،تقریبا هیچ پیکربندی برای map کردن دو type نیاز نیست."
می توانید از این لینک AutoMapper را بگیرید و sample ها و document ها را در آن ببینید.
استفاده از AutoMapper
حالا خواهیم دید که AutoMapper چگونه مشکل ما را حل خواهد کرد.AutoMapper متد CreateMap<T1,T2> را ایجاد میکند که این متد Mapping بین دو کلاس را انجام میدهد.بنابراین، این کد میتواند با کد زیر جایگزین شود:
public UserDto GetUserById(string id) { var userDto = new UserDto(); using(var context = new EntityDBContext()) { var user = context.Users.Where(ID => ID.user_id == id).FirstOrDefault(); Mapper.CreateMap<User,UserDto >(); userDto = Mapper.Map<User,UserDto >(user); } return userDto; }
User یک type از کلاس DBContext است و UserDTO ، کلاس DTO ماست که map میشود.
در آخر برای map کردن تمام داده ها به متد Map<T1,T2> از کلاس AutoMapper احتیاج داریم.بنابر این کد نهایی به صورت زیر است:
using(var context = new EntityDBContext()) { var users = (from users in context.Users select users).ToList() Mapper.CreateMap<User,UserDto >(); foreach(var user in users) { userDto = Mapper.Map<User,UserDto >(user); userDtosList.Add(userDto);     } }
بنابر این با این کار از روش خسته کننده ی قبلی نجات پیدا میکنیم.عملگر CRUD ما ساده و سازماندهی شده است.فقط کافی است که کلاس ها را map کنید و سپس عمل post را انجام دهید. برای بدست آوردن تمام جزئیات ، فقط نیاز داریم تا به کد قبلی یک تغییر بدهیم و آن هم این است که شئ UserDto را به لیست UserDTos اضافه کنیم.
Mapper.AssertConfigurationIsValid();
همچنین میتوانیم به جای Map از DynamicMap استفاده کنیم.
نکاتی که باید به یاد داشته باشید:
برای اینکه عمل mapping انجام شود باید نام هر دو کلاس یکسان باشد.همچنین، data type ها باید با هم match باشند. این به این معناست که اگر type A یک property دارد که از نوع long است،بنابراین type B هم باید property ای داشته باشد که از نوع long است.در غیر این صورت Automapper کار نمیکند.برای اینکه بفهمیم mapping ما کار میکند یا نه ، به صورت زیر عمل میکنیم:
Mapper.AssertConfigurationIsValid();
اگر کلاس های Dto و DBContext ، collection هایی را به عنوان property داشته باشند ، ما ابتدا باید آن کالکشن ها را map کنیم و سپس میتوانیم parent هارا map کنیم.بنابراین دو روش برای ایجاد map خواهیم داشت. بهتر است از آن در متد Initialize() استفاده کنیم.مانند زیر:
Mapper.Initialize(cfg => { cfg.CreateMap<User, UserDto>(); cfg.CreateMap<Recipts, ReciptsDto>(); });
متد ForMember()
متد مهم و پرکاربرد دیگری که AutoMapper برای ما فراهم کرده است ، متد ForMember() است.تصور کنید که کلاس dbContext ما ، دو property با نام های FirstName و LastName دارد، درحالیکه مدل یا viewmodel ما property ای با عنوان FullName را دارد .در این حالت نیازی نداریم که دو property جدید به مدل یا viewmodel مان اضافه کنیم.میتوانیم از متد ForMember() برای mapping استفاده کنیم.
Mapper.CreateMap<User,UserDto>().ForMember(user => user.Fullname,
map => map.MapFrom(p => p.FirstName + " " + p.LastName));
متد Ignore()
این متد زمانی کاربرد دارد که ما property اضافه ای در شئ مقصدمان داریم.این سناریو در ViewModel و هنگامی مورد استفاده قرار میگیرد که property اضافه ای داشته باشیم.بنابر این میتوانیم از کد زیر استفاده کنیم:
Mapper.CreateMap<User,UserDto >()
.ForMember(dt=>dt.SessionId,options=>options.Ignore())
.ForMember(dt=>dt.PROGRAM_NAME,options=>options.Ignore());
نتیجه:
با استفاده از AutoMapper زندگی راحت تر می شود. پیشنهاد میکنیم که برنامه نویسان اگر شرکت به آنها اجازه می دهد از این روش استفاده کنند.
میتوانید به این لینک مراجعه کنید و document ها و sample های مربوطه را مشاهده کنید.
- ASP.net MVC
- 3k بازدید
- 8 تشکر