- شما در هر دو حالت، دارای لیست منوهایی با 5 آیتم هستید. یعنی خروجی نهایی هر دو کوئری یکی هست و متد Cacheable درست عمل کردهاست.
- اینکه در کوئری بعدی LINQ to Objects شما، در حالت بدون Cacheable، «امکانات debug visualizer ویژوال استودیو» موفق به تشکیل روابط شدهاست، صرفا به عدم فراخوانی متد AsNoTracking در کوئری غیر کش شدهی شما بر میگردد. متد AsNoTracking جهت کاهش سربار کوئریهای EF و حذف پروکسیهای آن به صورت خودکار توسط متد Cacheable اعمال میشود؛ چون این نوع کوئریهای کش شده صرفا مختص به گزارشگیری هستند.
- اگر AsNoTracking فراخوانی شود، برای تشکیل روابط صرفا باید از متدهای Include و ThenInclude برای واکشی سطوح دیگر به هم مرتبط استفاده کنید. همچنین هر Include یا ThenInclude فقط یک سطح را واکشی میکند.
«... بدیهی است در اینجا هنوز روشهای Include و ThenInclue هم جواب میدهند؛ اما چون Lazy loading فعال نیست، عملا نمیتوان تمام زیر ریشهها را یافت ...»
در کل، کوئری دوم شما (حاصل نهایی واکشی تمام عناصر یک جدول) متصل به Context نیست و LINQ to Objects است. بنابراین زمانیکه لیست کامل عناصر را در حافظهی سمت کلاینت دارید (و در اینجا هر عملی بر روی این لیست دوم، نیازی به رفت و برگشت به بانک اطلاعاتی را ندارد)، تشکیل درخت آنها کار مشکلی نیست؛ چون هر آیتم، توسط خاصیت MenuId، به قبلی متصل است و یا خیر. در مثال زیر، لیست نهایی، بر اساس ReplyIdها (دقیقا همان اطلاعات اصلی که در بانک اطلاعاتی ذخیره میشود)، حاوی لیست Children چند سطحی خواهد شد. زمانی هم که این لیست را داشتید، از کلاس TreeViewHelper برای نمایش آن استفاده کنید.
- اینکه در کوئری بعدی LINQ to Objects شما، در حالت بدون Cacheable، «امکانات debug visualizer ویژوال استودیو» موفق به تشکیل روابط شدهاست، صرفا به عدم فراخوانی متد AsNoTracking در کوئری غیر کش شدهی شما بر میگردد. متد AsNoTracking جهت کاهش سربار کوئریهای EF و حذف پروکسیهای آن به صورت خودکار توسط متد Cacheable اعمال میشود؛ چون این نوع کوئریهای کش شده صرفا مختص به گزارشگیری هستند.
- اگر AsNoTracking فراخوانی شود، برای تشکیل روابط صرفا باید از متدهای Include و ThenInclude برای واکشی سطوح دیگر به هم مرتبط استفاده کنید. همچنین هر Include یا ThenInclude فقط یک سطح را واکشی میکند.
«... بدیهی است در اینجا هنوز روشهای Include و ThenInclue هم جواب میدهند؛ اما چون Lazy loading فعال نیست، عملا نمیتوان تمام زیر ریشهها را یافت ...»
در کل، کوئری دوم شما (حاصل نهایی واکشی تمام عناصر یک جدول) متصل به Context نیست و LINQ to Objects است. بنابراین زمانیکه لیست کامل عناصر را در حافظهی سمت کلاینت دارید (و در اینجا هر عملی بر روی این لیست دوم، نیازی به رفت و برگشت به بانک اطلاعاتی را ندارد)، تشکیل درخت آنها کار مشکلی نیست؛ چون هر آیتم، توسط خاصیت MenuId، به قبلی متصل است و یا خیر. در مثال زیر، لیست نهایی، بر اساس ReplyIdها (دقیقا همان اطلاعات اصلی که در بانک اطلاعاتی ذخیره میشود)، حاوی لیست Children چند سطحی خواهد شد. زمانی هم که این لیست را داشتید، از کلاس TreeViewHelper برای نمایش آن استفاده کنید.
void buildTreeLinqToObjects() { var comment1 = new BlogComment { Id = 1, Body = "نظر من این است که" }; var comment12 = new BlogComment { Id = 2, Body = "پاسخی به نظر اول", ReplyId = 1 }; var comment121 = new BlogComment { Id = 3, Body = "پاسخی به پاسخ به نظر اول", ReplyId = 2 }; var comment2 = new BlogComment { Id = 4, Body = "نظر من این بود که" }; var comment22 = new BlogComment { Id = 5, Body = "پاسخی به نظر قبلی", ReplyId = 4 }; var comment221 = new BlogComment { Id = 6, Body = "پاسخی به پاسخ به نظر من اول", ReplyId = 5 }; var list = new List<BlogComment> { comment1, comment12, comment121, comment2, comment22, comment221 }; foreach (var item in list) { if (item.ReplyId == null) { continue; } var parent = list.First(x => x.Id == item.ReplyId.Value); parent.Children.Add(item); } }