دوره آموزشی Entity FrameWork Core - قسمت هفدهم

دوره آموزشی Entity FrameWork Core - قسمت شانزدهمیکی از مزایای اصلی Entity FrameWork Core این است که مدل موجودیت ما نیازی به مطابقت با مدل ذخیره شده ما (مدل پایگاه داده) ندارد. تقسیم جدول(Table splitting) به ما این امکان را می دهد که چندین موجودیت را به یک جدول پایگاه داده نگاشت کنیم. تقسیم جدول درست برعکس تقسیم موجودیت(entity splitting) است. به عبارت دیگر، دو یا چند موجودیت از مدل ما به یک جدول پایگاه داده فیزیکی یکسان نگاشت می شوند. بیشتر بخوانید : نگاشت Table-per-Type و Table-per-Hierarchy Table Per Hierarchy یکی از انواع inheritance است و از یک جدول واحد در پایگاه داده برای نگهداری داده ها استفاده می کند و از چندین موجودیت در EF Core استفاده می کند. به عبارت دیگر، تقسیم جدول شامل نگاشت چندین موجودیت در یک لایه مفهومی به یک جدول واحد در یک لایه ذخیره (پایگاه داده) است. فرض کنید در پایگاه داده جدولی به نام EmployeeMaster برای ذخیره اطلاعات کارکنان داریم و در مدل دو موجودیت وجود دارد، یکی برای اطلاعات پایه ذخیره شده (کد و نام) و دیگری برای ذخیره اطلاعات اضافی (شماره تلفن و آدرس ایمیل). در اینجا جدول پایگاه داده تمام اطلاعات را در یک جدول فیزیکی ذخیره می کند.خوب تا اینجای کار متوجه شدیدم که EF Core اجازه می دهد تا دو یا تعداد بیشتری موجودیت را در یک ردیف نگاشت کنید. به این کار تقسیم جدول(table splitting) یا به اشتراک گذاری جدول (table sharing)می گویند.برای استفاده از تقسیم جدول، entity typeها باید به یک جدول نگاشت شوند، کلیدهای اولیه در همان ستون ها نگاشت شوند و حداقل یک رابطه بین کلید اصلی یک entity type و دیگری در همان جدول پیکربندی شود.یک سناریوی متداول برای تقسیم جدول استفاده از زیر مجموعه ای از ستون های جدول برای عملکرد بیشتر یا کپسوله سازی(encapsulation) است.در این مثال Order زیر مجموعه ای از DetailedOrder را نشان می دهد. public class Order { public int Id { get; set; } public OrderStatus? Status { get; set; } public DetailedOrder DetailedOrder { get; set; } } public enum OrderStatus { Pending, Shipped }و در ادامه :public class DetailedOrder { public int Id { get; set; } public OrderStatus? Status { get; set; } public string BillingAddress { get; set; } public string ShippingAddress { get; set; } public byte[] Version { get; set; } }علاوه بر پیکربندی فوق Property(o => o.Status).HasColumnName(&quotStatus&quot) را برای نگاشت DetailedOrder.Status به همان ستون Order.Status می نامیم.modelBuilder.Entity<DetailedOrder>( dob => { dob.ToTable(&quotOrders&quot); dob.Property(o => o.Status).HasColumnName(&quotStatus&quot); }); modelBuilder.Entity<Order>( ob => { ob.ToTable(&quotOrders&quot); ob.Property(o => o.Status).HasColumnName(&quotStatus&quot); ob.HasOne(o => o.DetailedOrder).WithOne() .HasForeignKey<DetailedOrder>(o => o.Id); ob.Navigation(o => o.DetailedOrder).IsRequired(); });ذخیره(Saving) و پرس و جوی(querying) موجودیت ها با استفاده از تقسیم جدول مانند سایر موجودیت ها انجام می شود:using (var context = new TableSplittingContext()) { context.Database.EnsureDeleted(); context.Database.EnsureCreated(); context.Add( new Order { Status = OrderStatus.Pending, DetailedOrder = new DetailedOrder { Status = OrderStatus.Pending, ShippingAddress = &quot221 B Baker St, London&quot, BillingAddress = &quot11 Wall Street, New York&quot } }); context.SaveChanges(); } using (var context = new TableSplittingContext()) { var pendingCount = context.Orders.Count(o => o.Status == OrderStatus.Pending); Console.WriteLine($&quotCurrent number of pending orders: {pendingCount}&quot); } using (var context = new TableSplittingContext()) { var order = context.DetailedOrders.First(o => o.Status == OrderStatus.Pending); Console.WriteLine($&quotFirst pending order will ship to: {order.ShippingAddress}&quot); }اگر تمام ستون های استفاده شده توسط یک موجودیت وابسته در پایگاه داده NULL باشند، در هنگام پرس و جو هیچ نمونه ای برای آن ایجاد نخواهد شد. این اجازه می دهد تا یک موجودیت وابسته اختیاری را مدل سازی کنید، که در آن ویژگی رابطه در اصل تهی خواهد بود. توجه داشته باشید که اگر همه ویژگی های وابسته اختیاری باشند و روی null تنظیم شوند، این اتفاق می افتد، که ممکن است مورد انتظار نباشد.توکن های همزمانی(Concurrency tokens) :اگر هر یک از انواع موجودیت هایی که یک جدول را به اشتراک می گذارند دارای Concurrency token باشد، باید در همه انواع موجودیت های دیگر نیز گنجانده شود. این برای جلوگیری از stale concurrency token value، زمانی که تنها یکی از موجودیت های نگاشت شده در همان جدول به روز می شود، ضروری است.برای جلوگیری از stale concurrency token value می توان آن را به عنوان shadow property تعریف کرد :modelBuilder.Entity<Order>() .Property<byte[]>(&quotVersion&quot).IsRowVersion().HasColumnName(&quotVersion&quot); modelBuilder.Entity<DetailedOrder>() .Property(o => o.Version).IsRowVersion().HasColumnName(&quotVersion&quot);جمع بندی در سناریو هایی که تعداد ستون‌های یک جدول، بیش از اندازه زیاد می‌شوند و یا آن جدول حاوی فیلدهایی است که منابع حافظه ای زیادی مصرف می‌کنند و به هنگام واکشی اطلاعات آن جدول همیشه نیازی به داده‌های آن فیلد‌ها نداریم و در نتیجه با واکشی بی مورد آن ها، سربار اضافه ای به سیستم خود تحمیل می‌کنیم، راه حل استفاده از table spliting خواهد بود.بیشتر بخوانید : دوره آموزشی Entity FrameWork Core - قسمت هجدهمبیشتر بخوانید : دوره آموزشی Entity FrameWork Coreبیشتر بخوانید : نقشه راه توسعه دهندگان Asp.NET Corehttps://zarinp.al/farshidazizi