انجام عملیات CRUD با استفاده از AutoMapper در MVC
جمعه 24 اردیبهشت 1395در این مقاله با استفاده از AutoMapper و تکنولوژی MVC ، در چند مرحله ساده عملیات CRUD را پیاده سازی می کنیم. همچنین مفاهیم مربوط به AutoMapper و کاربرد های آن را بیان می کنیم.
مقدمه
وقتی با realtime programming (برنامه نویسی برای سیستم های بلادرنگ) سر و کار داریم ، با چالش های زیادی مواجه می شویم. این مقاله یک مفهوم جدید به نام Auto Mapper را در MVC معرفی می کند که به وسیله آن می توانیم بر چالش های بزرگی که برای ارتباط با Data Entity و bind کردن داده ها به model مواجه هستیم ، غلبه کنیم.
چالش های موجود
برخی اوقات هنگام مواجه شدن با Entity های بلادرنگ (real time) و متصل کردن آن ها به model هایمان ، به حالت زیر می رسیم :
var dbContext = new MyDBDataContext(); var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id); var user = new LearningMVC.Models.User(); if (userDetails != null) { user.UserId = userDetails.UserId; user.FirstName = userDetails.FirstName; user.LastName = userDetails.LastName; user.Address = userDetails.Address; user.PhoneNo = userDetails.PhoneNo; user.EMail = userDetails.EMail; user.Company = userDetails.Company; user.Designation = userDetails.Designation; } return View(user);
درک مفهوم کدی که در بالا نوشته شده است، چندان سخت نیست. در کد بالا ، یک نمونه از MyDBDataContext به وسیله ی LinqTOSql Context class ساخته شده است (using "var dbContext = new MyDBDataContext();") سپس جزئیات اطلاعات کاربر از یک جدول خاص گرفته می شوند و در متغیر userDetails ذخیره می شوند. ما یک مدل از پیش ساخته شده به نام "User" داریم ("LearningMVC.Models.User()") ، که دارای Property های مشابه با Users class هایی است که از پایگاه داده تولید شده اند. حالا ما Property های نمونه ای که از model ساختیم را با Property های نمونه ای که از User class (از پایگاه داده) ساختیم ، مقداردهی می کنیم ، به این روشی که گفتیم می توانیم view ها را در MVC پر کنیم .
در اینجا می بینیم که 8 خصوصیت (Property) مشابه داریم که هر کدام در کلاس جداگانه ای قرار دارند، یکی از آن ها در Model قرار دارد و یکی دیگر در Users class قرار دارد. و کاری که ما می خواهیم انجام بدهیم این است که می خواهیم این property ها را یکی یکی به model وصل کنیم و سپس model را به View متصل کنیم. حالا می خواهیم بببینیم مشکل این روش کجاست ؟ اگر ما 100 ستون از اطلاعات داشته باشیم که از پایگاه داده گرفته شوند و همچنین مدل ما هم همین تعداد از property ها را داشته باشد، و بخواهیم کد را 7-6 بار در زمان های متفاوت و به طریق مختلف تکرار کنیم ، آیا ما همچنان از این سیاست استفاده خواهیم کرد؟ سیاستی که هر بار هر کدام از Property ها را از پایگاه داده بگیریم و به model وصل کنیم! باور کنید اگر بخواهیم به این روش ، این برنامه را بنویسیم ، زمان طولانی ای را از ما خواهد گرفت .
برای غلبه بر چنین مشکلاتی ، AutoMapper به بازار آمد. این روش ، به کار و تلاش کمتری نیاز دارد و همچنین زمان اجرا را تا حد زیادی کاهش می دهد.
Auto Mapper
AutoMapper یک تکنولوژی است که به صورت open source در GitHub نیز ارائه شده است.
همانطور که در صفحه ی AutoMapper CodePlex web page نیز گفته شده است ، AutoMapper یک object-object mapper است . (شی را به شی می نگارد.) Object-object mapping به این روش کار می کند که یک شی ورودی با یک نوع خاصی را می گیرد و در خروجی یک شی با نوع دیگری را تحویل می دهد. (شی ورودی را به یک شی دیگر تبدیل می کند و به عنوان خروجی تحویل می دهد) . نکته ای که AutoMapper را برای ما جالب می کند این است که AutoMapper می تواند با استفاده از یک سری قوانین و قواعد مفید و جالب، حتی در یک کد کثیف و طولانی ، یک روش mapping بهینه و خوب به ما بدهد. تا زمانی که نوع B از قوانین AutoMapper (که در زمان ساخت ارتباط، ایجاد شده اند) پیروی کند، هیچ گونه پیکر بندی ای برای map کردن دو نوع داده A و B نیاز نیست.بنابراین ، AutoMapper راه حل مناسبی برای حل مشکلات mapping ما محسوب می شود.
نصب AutoMapper
ابتدا باید NuGet Package Manager را بر روی Visual Studio IDE نصب کنید. پس از انجام این کار، مسیر زیر را طی کنید:
"Tools" -> "Library Packet Manager" -> "Packet manager Console"
سپس در پنجره ای که در انتهای صفحه باز می شود ، عبارت زیر را تایپ کنید :
PM> Install-Package AutoMapper
کلید Enter را فشار دهید. به این وسیلهAutoMapper نصب می شود و به صورت یک DLL به قسمت reference پروژه ی شما اضافه می شود و می توانیم به راحتی از آن استفاده کنیم.
AutoMapper در عمل چگونه کار می کند؟
ابتدا یک برنامه MVC ایجاد می کنیم. در فایل ضمیمه ای که به همراه مقاله در اختیار شما گذاشته شده است، یک برنامه هم قرار دارد که بدون AutoMapper کار می کند.
حالا بیایید همه ی Action های Controller ها را یکی یکی ارزیابی کنیم و code را با استفاده از AutoMapper دوباره بازنویسی کنیم.
مرحله 1 : یک پایگاه داده برای برنامه ایجاد کنید. فایل Script پایگاه داده در فایل ضمیمه موجود است.
برنامه ای که در فایل ضمیمه وجود دارد را در برنامه Visual Studio باز کنید.
همانطور که می بینید AutoMapper در پروژه ، reference داده شده است. حالا از فضای نام AutoMapper مطابق شکل زیر استفاده می کنیم :
مرحله 2 : Index Action
در Index Action در قسمت MyController (که در پوشه Controllers قرار دارد) ، کد زیر قرار دارد:
public ActionResult Index() { var dbContext = new MyDBDataContext(); var userList = from user in dbContext.Users select user; var users = new List<LearningMVC.Models.User>(); if (userList.Any()) { foreach (var user in userList) { users.Add(new LearningMVC.Models.User() { UserId = user.UserId, Address = user.Address, Company = user.Company, FirstName = user.FirstName, LastName = user.LastName, Designation = user.Designation, EMail = user.EMail, PhoneNo = user.PhoneNo }); } } return View(users); }
در این کد ، AutoMapper کجا قرار می گیرد؟ AutoMapper باید در جایی قرار بگیرد که بتواند Map کردن همه Property ها را انجام بدهد. بنابراین باید در سطر اول این کد، AutoMapper را تعریف کنیم.
یک mapping پیش فرض ، با نام "Mapper.CreateMap<T1, T2>()" با نوع های داده ای مناسب ایجاد می کنیم. در این مورد ، T1 ، همان "LearningMVC.User" و T2 نیز همان "LearningMVC.Models.User" خواهد بود.
Mapper.CreateMap<LearningMVC.User, LearningMVC.Models.User>(); LearningMVC.User -> DTO Object Class LearningMVC.Models.User -> Model Class to bind the View
در اینجا ما یک mapping بین DTO و یک Model class ، با استفاده از کلاس AutoMapper ایجاد می کنیم.
کد زیر را در داخل حلقه foreach قرار بدهید.
LearningMVC.Models.User userModel = Mapper.Map<LearningMVC.User, LearningMVC.Models.User>(user); users.Add(userModel);
در مرحله ی آخر، باید Mapper.Map<T1, T2>(obj1) را فراخوانی کنیم تا شی T2 که map شده است را به ما برگرداند.
کد نهایی ما به صورت زیر خواهد بود :
public ActionResult Index() { Mapper.CreateMap<LearningMVC.User, LearningMVC.Models.User>(); var dbContext = new MyDBDataContext(); var userList = from user in dbContext.Users select user; var users = new List<LearningMVC.Models.User>(); if (userList.Any()) { foreach (var user in userList) { LearningMVC.Models.User userModel = Mapper.Map<LearningMVC.User, LearningMVC.Models.User>(user); users.Add(userModel); } } return View(users);
}
به وسیله این کار ، ما از کار خسته کننده وصل کردن Property ها به هم رهایی پیدا کردیم. حالا برنامه را اجرا کنید. می بینید که برنامه به درستی کار می کند.
مرحله 3 : Details Action (بخش جزئیات)
کدی که در حال حاضر داریم :
public ActionResult Details(int? id) { var dbContext = new MyDBDataContext(); var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id); var user = new LearningMVC.Models.User(); if (userDetails != null) { user.UserId = userDetails.UserId; user.FirstName = userDetails.FirstName; user.LastName = userDetails.LastName; user.Address = userDetails.Address; user.PhoneNo = userDetails.PhoneNo; user.EMail = userDetails.EMail; user.Company = userDetails.Company; user.Designation = userDetails.Designation; } return View(user); {
کد جدیدی که با استفاده ازAutoMapper کار می کند:
public ActionResult Details(int? id) { var dbContext = new MyDBDataContext(); Mapper.CreateMap<LearningMVC.User, LearningMVC.Models.User>(); var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id); LearningMVC.Models.User user = Mapper.Map<LearningMVC.User, LearningMVC.Models.User>(userDetails); return View(user); }
مرحله 4 : Create Action(بخش ایجاد یک کاربر جدید)
کدی که در حال حاضر داریم :
[HttpPost] public ActionResult Create(LearningMVC.Models.User userDetails) { try { var dbContext = new MyDBDataContext(); var user = new User(); if (userDetails != null) { user.UserId = userDetails.UserId; user.FirstName = userDetails.FirstName; user.LastName = userDetails.LastName; user.Address = userDetails.Address; user.PhoneNo = userDetails.PhoneNo; user.EMail = userDetails.EMail; user.Company = userDetails.Company; user.Designation = userDetails.Designation; } dbContext.Users.InsertOnSubmit(user); dbContext.SubmitChanges(); return RedirectToAction("Index"); } catch { return View(); } }
کد جدیدی که با استفاده از AutoMapper کار می کند :
[HttpPost] public ActionResult Create(LearningMVC.Models.User userDetails) { try { Mapper.CreateMap<LearningMVC.Models.User, LearningMVC.User>(); var dbContext = new MyDBDataContext(); var user = Mapper.Map<LearningMVC.Models.User, LearningMVC.User>(userDetails); dbContext.Users.InsertOnSubmit(user); dbContext.SubmitChanges(); return RedirectToAction("Index"); } catch { return View(); } }
در این کد ها ما با استفاده از mapping ، کارهای مربوط به جابجایی را انجام دادیم. زیرا برای ایجاد Create Action، نیاز داریم که داده ها را از Model بخوانیم و آن ها را به DTO متصل کنیم .در این کد ها T1 مدل ما است و T2 نیز به منزله DTO است.
مرحله 5 : Edit Action (بخش مربوط به ویرایش )
کدی که در حال حاضر داریم :
public ActionResult Edit(int? id) { var dbContext = new MyDBDataContext(); var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id); var user = new LearningMVC.Models.User(); if (userDetails != null) { user.UserId = userDetails.UserId; user.FirstName = userDetails.FirstName; user.LastName = userDetails.LastName; user.Address = userDetails.Address; user.PhoneNo = userDetails.PhoneNo; user.EMail = userDetails.EMail; user.Company = userDetails.Company; user.Designation = userDetails.Designation; } return View(user); }
کد جدیدی که با استفاده از AutoMapper کار می کند :
public ActionResult Edit(int? id) { Mapper.CreateMap<LearningMVC.User, LearningMVC.Models.User>(); var dbContext = new MyDBDataContext(); var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id); var user = Mapper.Map<LearningMVC.User, LearningMVC.Models.User>(userDetails) return View(user); }
مرحله 6 : Delete Action (بخش مربوط به حذف)
کدی که در حال حاضر داریم :
public ActionResult Delete(int? id) { var dbContext = new MyDBDataContext(); var user = new LearningMVC.Models.User(); var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id); if (userDetails != null) { user.FirstName = userDetails.FirstName; user.LastName = userDetails.LastName; user.Address = userDetails.Address; user.PhoneNo = userDetails.PhoneNo; user.EMail = userDetails.EMail; user.Company = userDetails.Company; user.Designation = userDetails.Designation; } return View(user); }
کد جدیدی که با استفاده از AutoMapper کار می کند :
public ActionResult Delete(int? id) { var dbContext = new MyDBDataContext(); Mapper.CreateMap<LearningMVC.User, LearningMVC.Models.User>(); var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id); var user = Mapper.Map<LearningMVC.User, LearningMVC.Models.User>(userDetails); return View(user); }
ForMember() و MapFrom() در AutoMapper
دو تابع مهمی که در AutoMapper وجود دارند و نقش مهمی در object mapping ایجاد می کنند ، دو تابع ForMember() و MapFrom() هستند. برای درک بهتر کارایی آن ها یک مثال میزنم. فرض کنید کلاس model/viewmodel یک Property به نام FullName دارد و ما می خواهیم FirstName (نام) و Last Name (نام خانوادگی) کاربر را از DTO بگیریم و به model متصل کنیم. برای از بین بردن این پیچیدگی و کار زیاد، از ForMember() و MapFrom() استفاده می کنیم. کد زیر را ببینید:
Mapper.CreateMap<LearningMVC.User, LearningMVC.Models.User>().ForMember(emp => emp.Fullname, map => map.MapFrom(p => p.FirstName + " " + p.LastName));
در این تکه کد می گوییم: ForMember FullName در بخش model class ما ، Property های FirstName و LastName را از map,DTO می کند.
کد، خودش به تنهایی بیانگر عملکردی که انجام می دهد، است.این نوع Custom Mapping ، mapping نامیده می شود.
آموزش asp.net mvc
- ASP.net MVC
- 2k بازدید
- 4 تشکر