ورود

View Full Version : طراحی ویومدل با جداول چند به چند



sara_t
جمعه 22 تیر 1397, 22:03 عصر
سلام دوستان

من میخام برای جدول جزییات محصول یک ویومدل داشته باشم .ممنون میشم بگید چطور میتونم ویومدل رو برای این جدول طراحی کنم؟

جدول محصول با چند جدول دیگه رابطه چندبه چند داره بصورت زیر :

product.cs


public class Product
{
public int Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public virtual ICollection<ProductComment> ProductComments { get; set; } = new HashSet<ProductComment>();
public virtual ICollection<ProductGroup> ProductGroups { get; set; } = new HashSet<ProductGroup>();
public virtual ICollection<ProductMedia> ProductMedias { get; set; } = new HashSet<ProductMedia>();


Media.cs


public class Media
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<ProductMedia> ProductMedias { get; set; } = new HashSet<ProductMedia>();
}



ProductMedia.cs


public class ProductMedia
{
public int MediaId { get; set; }
public virtual Media Media { get; set; }
public int ProductId { get; set; }
public virtual Product Product{ get; set; }
public string Description { get; set; }
}


بقیه جداول هم روابطشون با جدول محصولات به همین صورته . میخام یه ویو مدل داشته باشم و تمام این فیلدها در اون باشه . در ویومدلهای جداوا چند به چند باید مثه کلاسها رابطه ها هم نوشته بشه؟

ali_md110
شنبه 23 تیر 1397, 01:23 صبح
ویو مدل از نامش پیداست: مدل هایی حاوی یک یا چند فیلد که برای نمایش در ویو ساخته میشوند و نیازی به ایجاد روابط یک به چند یا چند به چند ندارند
این ویومدلها در واقع داده های واکشی شده توسط کوئری در اختیارشون قرار داده میشه و درون آنها ریخته میشه

اگر میخواهید تمام فیلدهای دلخواهتون مثلا Title از جدول Product و Name از جدول Media و یا سایر فیلدهای دیگر همگی با یک اکشن و یک کوئری نمایش بدید همه فیلدهای مورد نیاز رو درون یک ویو مدل قرار بدید و با projction داده ها رو از دیتابیس بگیرید و در این ویومدل بریزید
و یا اگر در صفحه مشخصات کالا جند قسمت مختلف از مشخصات کالا دارید و از پارشل ویو استفاده میکنید باید ویومدهای مختلف بسازید
و هرکدوم جداگانه داده هاشون از دیتابیس دریافت کنند

2khtarbache
شنبه 23 تیر 1397, 09:00 صبح
سلام.
شما باید مشخص کنید کدام آیتم ها را در ویو نیاز دارید. و سپس همان آیتم ها را در ویومدل قرار بدهید. در ویومدل ها ارتباط بین انتیتی ها نوشته نمیشود.
شما فرض کنید برای کلاس ProductMedia میخواهید یک ویو مدل بنویسید؛ این کلاس شامل یک پراپرتی به نام Media است. اگر شما فرضا فقط به پراپرتی Name از کلاس Media نیاز داشته باشید نیازی نیست در ویو مدل پراپرتی معادل Media در کلاس مدل ProductMedia را هم داشته باشید و شما میتوانید پراپرتی جدیدی فرضا با نام MediaName در ویومدل خود داشته باشید. و در لایه ی Mapper خود مشخص کنید که منظور از MediaName پراپرتی Name از کلاس Media است.

sara_t
یک شنبه 24 تیر 1397, 23:24 عصر
ممنون
وقتی تعداد آیتمهای ویو مدل کم هست نیاز به projection هست ؟ اینکه من یه لیست از داده های موردنظرم رو بگیرم و بعد با استفاده از یه حلقه for ، داده های لیست رو به آیتمهای ویومدل منتقل کنم ؟

و اینکه من میتونم یه ویومدل داشته باشم و در تعداد زیادی query ، ویومدل رو new کنم و اطلاعات query های مختلف رو توی ویومدل قرار بدم ؟

ali_md110
دوشنبه 25 تیر 1397, 00:27 صبح
فرقی نمیکنه شما با یک حلقه for هم میتونید viewModel را از داده پر کنید
ولی توجه داشته باشید که اگر projetion و اونهم استفاده از ابزای مثل Automapper بکار برده بشه کارایی بسیار بالاتر خواهد رفت
مخصوصا اینکه از ProjectTo استفاده کنید automapper بصورت اتوماتیک eager loading رابرای شما برقرار میکند و join های اضافی ها را شناسایی و صرفه نظر میکند

جواب سوال دوم شما بله هست
viewModel یک کلاس حاوی فیلدهای مورد نظر هست و به ازای هر new شدن یک جایی در حافظه اشغال میکند و بگارگیری چند باره آن هیچ اشکالی ندارد و سودمند هم هست

sara_t
دوشنبه 25 تیر 1397, 18:09 عصر
بسیار ممنونم .

من برای گرفتن مقادیر از جدول محصولات و مدیا بصورت زیر عمل کردم (دو بار query گرفتم که join های کمتری داشته باشم و نمیدونم واقعا این روش درستتره یا اینکه تمام جداول رو با هم join بزنم؟) ولی تو این حالت چون مقادیر برای ویو مدل دوبار پر میشن من چطور میتونم از mapper استفاده کنم ؟



public List<ProductViewModel> ShowNewProduct(int count)
{
var qNewPro = context.Products
.OrderByDescending(c => c.Id)
.Take(count)
.ToList();
List<ProductViewModel> lstNewProduct = new List<ProductViewModel>();
foreach (var item in qNewPro)
{
ProductViewModel vmNewPro = new ProductViewModel();
vmNewPro.Id = item.Id;
vmNewPro.Title = item.Title;
vmNewPro.ImageUrl = context.ProductMedias
.Where(c => c.ProductId == item.Id)
.Select(c => c.Media.Name)
.FirstOrDefault();
lstNewProduct.Add(vmNewPro);
}
return lstNewProduct ?? null;
}



برای متدهایی که از یک query استفاده میکنن اول سرویس mapper رو در استارت آپ فعال کردم و بعد :



public List<GroupViewModel> ShowGroup()
{
var qGroup = context.Groups
.ToList();
return Mapper.Map<List<Group>,List<GroupViewModel>>(qGroup) ?? null;
}

ali_md110
دوشنبه 25 تیر 1397, 19:24 عصر
یک سوال؟
شما وقتی تمام کالاهای جدید را به کاربران نمایش می دهید آیا همزمان جزئیاتشان از جدول ProductMedia را هم نشان می دهید؟
یا اینکه کاربر با انتخاب کالا جزئیات به او نشان داده میشود؟
اگر مورد دوم هست میتونید از این حلقه استفاده کنید ولی توجه داشته باشید که دو کوئری ارسال خواهد شد
و اگر مورد اول هست
شما به نظر خودتون دوبار query دارید و جوین کمتر ولی در واقع کوئری های زیادی حمله ور میشوند به سمت سرور
این روش را به هیچ وجه بکار نبرید پیشنهاد میدم یک ابزار profiler نصب کنید و اونوقت ببینید که در حلقه ای که ساختید چند کوئری به سمت دیتابیس صادر میشود

دستورات include و SelectMany برای مدیریت joinها و روابط Hierarchical
هست



context.Products.Include(m => m.ProductMedias).Select(m => view model ra inja fill konid).ToList();

sara_t
شنبه 30 تیر 1397, 13:20 عصر
زمانیکه من به داده های جدول Media هم نیاز دارم چطور میتونم با یک query به تمام داده ها دسترسی داشته باشم ؟

اگر کد رو هم بصورت زیر بنویسم ، به فیلد Media.Name به چه صورتی میشه دسترسی داشت ؟




var qNewPro = context.Products
.Include(p => p.ProductMedias)
.ThenInclude(p => p.Media)



ممنونم

ali_md110
شنبه 30 تیر 1397, 20:50 عصر
میتونید بدینصورت عمل کنید



var list= context.Products
.Include(e => e.ProductMedias)
.ThenInclude(e => e.Media)
.ToList();

foreach (var p in list)
{
Console.WriteLine({p.نام فیلد}");
foreach (var t in p.ProductMedias.Select(e => e.Media))
{
Console.WriteLine(t.فیلد مدیا);
}
}

sara_t
یک شنبه 31 تیر 1397, 09:33 صبح
بسیار ممنون.من نمیتونم e.media رو در همون query به list بدم ؟ و باید از for استفاده کنم . در اینصورت برای یه همچین query هایی چطور میتونم از mapper استفاده کنم ؟ یا دیگه توی همون حلقه های for ویومدل رو new کنم و داده ها رو پاس بدم ؟

ali_md110
یک شنبه 31 تیر 1397, 13:46 عصر
لینک زیر یه توضیحاتی دادم ببینید شاید راهنمایی کرد
مورد Automapper هم مد نظر داشته باشید
http://barnamenevis.org/showthread.php?550025