از کتابخانهی DNTPersianUtils.Core استفاده کنید (با NET 4.x. و همچنین NET Core. سازگار است):
"1395/11/3 7:30".ToGregorianDateTime()
public abstract class BaseEntity { public int Id { set; get; } } public class User : BaseEntity { public string Name { set; get; } public virtual ICollection<Advertisement> Advertisements { get; set; } } public class Advertisement : BaseEntity { public string Title { get; set; } public string Description { get; set; } [ForeignKey("UserId")] public virtual User User { get; set; } public int UserId { get; set; } }
public class AdvertisementViewModel { public int Id { get; set; } public string Title { get; set; } public int UserId { get; set; } } public class UserViewModel { public int Id { set; get; } public string Name { set; get; } public List<AdvertisementViewModel> Advertisements { get; set; } }
به روز رسانی خواص راهبری Entity framework توسط AutoMapper
در کلاسهای فوق، یک کاربر، تعدادی تبلیغات را میتواند ثبت کند. در این حالت اگر بخواهیم خاصیت User کلاس Advertisement را توسط AutoMapper به روز کنیم، با رعایت دو نکته، اینکار به سادگی انجام خواهد شد:
الف) همانطور که در کلاس Advertisement جهت تعریف کلید خارجی مشخص است، UserId نیز علاوه بر User ذکر شدهاست. این مورد کار نگاشت UserId اطلاعات دریافتی از کاربر را ساده کرده و در این حالت نیازی به یافتن اصل User این UserId از بانک اطلاعاتی نخواهد بود.
ب) چون در اطلاعات دریافتی از کاربر تنها Id او را داریم و نه کل شیء مرتبط را، بنابراین باید به AutoMapper اعلام کنیم تا از این خاصیت صرفنظر کند که اینکار توسط متد Ignore به نحو ذیل قابل انجام است:
this.CreateMap<AdvertisementViewModel, Advertisement>() .ForMember(advertisement => advertisement.Description, opt => opt.Ignore()) .ForMember(advertisement => advertisement.User, opt => opt.Ignore());
به روز رسانی مجموعههای Entity Framework توسط AutoMapper
فرض کنید چنین اطلاعاتی از کاربر و رابط کاربری برنامه دریافت شده است:
var uiUser1 = new UserViewModel { Id = 1, Name = "user 1", Advertisements = new List<AdvertisementViewModel> { new AdvertisementViewModel { Id = 1, Title = "Adv 1", UserId = 1 }, new AdvertisementViewModel { Id = 2, Title = "Adv 2", UserId = 1 } } };
var dbUser1 = ctx.Users.Include(user => user.Advertisements).First(x => x.Id == uiUser1.Id); Mapper.Map(source: uiUser1, destination: dbUser1);
this.CreateMap<UserViewModel, User>()
علت را در این دو تصویر بهتر میتوان مشاهده کرد:
تصویر اول که مستقیما از بانک اطلاعاتی حاصل شدهاست، دارای پروکسیهای EF است. اما در تصویر دوم، جایگزین شدن این پروکسیها را مشاهده میکنید که سبب خواهد شد این اشیاء دیگر تحت نظارت EF نباشند.
راه حل:
در این مورد خاص باید به AutoMapper اعلام کنیم تا کاری با لیست تبلیغات کاربر دریافت شدهی از بانک اطلاعاتی نداشته باشد و آنرا راسا جایگزین نکند:
this.CreateMap<UserViewModel, User>().ForMember(user => user.Advertisements, opt => opt.Ignore());
سپس کار ثبت یا به روز رسانی را به صورت نیمه خودکار مدیریت میکنیم:
using (var ctx = new MyContext()) { var dbUser1 = ctx.Users.Include(user => user.Advertisements).First(x => x.Id == uiUser1.Id); Mapper.Map(source: uiUser1, destination: dbUser1); foreach (var uiUserAdvertisement in uiUser1.Advertisements) { var dbUserAdvertisement = dbUser1.Advertisements.FirstOrDefault(ad => ad.Id == uiUserAdvertisement.Id); if (dbUserAdvertisement == null) { // Add new record var advertisement = Mapper.Map<AdvertisementViewModel, Advertisement>(uiUserAdvertisement); dbUser1.Advertisements.Add(advertisement); } else { // Update the existing record Mapper.Map(uiUserAdvertisement, dbUserAdvertisement); } } ctx.SaveChanges(); }
- سپس بر روی اطلاعات تبلیغات دریافتی از کاربر، یک حلقه را تشکیل خواهیم داد. در اینجا هربار بررسی میکنیم که آیا معادل این تبلیغ هم اکنون به شیء db user متصل است یا خیر؟ اگر متصل نبود، یعنی یک رکورد جدید است و باید Add شود. اگر متصل بود صرفا باید به روز رسانی صورت گیرد.
- برای حالت ایجاد شیء جدید بانک اطلاعاتی، بر اساس uiUserAdvertisement دریافتی، میتوان از متد Mapper.Map استفاده کرد؛ خروجی این متد، یک شیء جدید تبلیغ است.
- برای حالت به روز رسانی اطلاعات db user موجود، بر اساس اطلاعات ارسالی کاربر نیز میتوان از متد Mapper.Map کمک گرفت.
نکتهی مهم
چون در اینجا از متد Include استفاده شدهاست، فراخوانیهای FirstOrDefault داخل حلقه، سبب رفت و برگشت اضافهتری به بانک اطلاعاتی نخواهند شد.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید:
AM_Sample04.zip
سری مقدماتی ASP.NET Core
Introduction to ASP.NET Core part 15: starting with tag helpers
Introduction to ASP.NET Core part 14: the view start and the layout files
Introduction to ASP.NET Core part 13: the view imports file
Introduction to ASP.NET Core part 12: data annotation of view models
Introduction to ASP.NET Core part 11: inserting a new Book in a form
Introduction to ASP.NET Core part 10: the details page and more on view models
Introduction to ASP.NET Core part 9: MVC continued with routing
Introduction to ASP.NET Core part 8: MVC continued with controller actions and our first view
Introduction to ASP.NET Core part 7: starting with MVC
Introduction to ASP.NET Core part 6: environments and settings
Introduction to ASP.NET Core part 5: static files
Introduction to ASP.NET Core part 4: middleware and the component pipeline
Introduction to ASP.NET Core part 3: the configuration file
Introduction to ASP.NET Core part 2: dependencies and dependency injection
Introduction to ASP.NET Core part 1: anatomy of an empty web project
افزونهی Version Lens برای VSCode
Autofac 4 core منتشر شد
فریم ورک سئو برای ASP.NET Core
Following my last post on my ASP.NET MVC SEO-Framework I started looking at adding support also for ASP.NET Core MVC, with its superior Dependency Injection and Tag Helpers.