بارگذاری Entity های مرتبط در Entity Framework
پنجشنبه 20 آبان 1395EF از سه روش برای بارگذاری داده های مرتبط پشتیبانی میکند . eager loadin و lazy loading و explicit loading ... در این مقاله با استفاده از Code First به بررسی این روش ها خواهیم پرداخت .
Eagerly Loading :
Eagerly Loading یک پردازش است که با آن یک کوئری برای یک نوع Entity ، Entity های مرتبط را نیز به عنوان قسمتی از کوئری بارگذاری میکند . Eagerly Loading بوسیله استفاده از متد Include حاصل میشود . برای مثال ، کوئری زیر blogها و همه پست های مرتبط با آن blog را بارگذاری میکند .
using (var context = new BloggingContext()) { // Load all blogs and related posts var blogs1 = context.Blogs .Include(b => b.Posts) .ToList(); // Load one blogs and its related posts var blog1 = context.Blogs .Where(b => b.Name == "ADO.NET Blog") .Include(b => b.Posts) .FirstOrDefault(); // Load all blogs and related posts // using a string to specify the relationship var blogs2 = context.Blogs .Include("Posts") .ToList(); // Load one blog and its related posts // using a string to specify the relationship var blog2 = context.Blogs .Where(b => b.Name == "ADO.NET Blog") .Include("Posts") .FirstOrDefault(); }
توجه داشته باشید که Include یک extension method است که در فضانام System.Data.Entity وجود دارد ، پس مطمئن شوید که از این فضانام استفاده کرده باشید .
بارگذاری Eagerly چند سطحی :
همچنین امکان بارگذاری Eagerly چند سطحی entity های مرتبط نیز وجود دارد . به مثال زیر توجه کنید :
using (var context = new BloggingContext()) { // Load all blogs, all related posts, and all related comments var blogs1 = context.Blogs .Include(b => b.Posts.Select(p => p.Comments)) .ToList(); // Load all users their related profiles, and related avatar var users1 = context.Users .Include(u => u.Profile.Avatar) .ToList(); // Load all blogs, all related posts, and all related comments // using a string to specify the relationships var blogs2 = context.Blogs .Include("Posts.Comments") .ToList(); // Load all users their related profiles, and related avatar // using a string to specify the relationships var users2 = context.Users .Include("Profile.Avatar") .ToList(); }
توجه داشته باشید که در حال حاضر امکان فیلتر گذاشتن روی entity های مرتبط بارگذاری شده وجود ندارد . Include همیشه در Entityهای مرتبط میآیند .
Lazy Loading :
Lazy Loading پردازشی است که در طی آن یک entity با لیستی از entity ها ، اولین باری که یک Property به این entity یا entityها ارجاع داده شوند ، بصورت خودکار از پایگاه داده بارگذاری میشوند . زمانی که از نوع POCO در entity استفاده میکنیم ، lazy loading بوسیله ایجاد یک نمونه از نوع مشتق شده Proxy حاصل میشود و سپس برای اضافه کردن بارگذاری مشخصه های مجازی را Override میکند . برای مثال ، زمانی که از کلاس Blog entity زیر استفاده میکنیم ، پست های مرتبط نیز در دفعه ی اولی که مشخصه ی Post navigation پردازش میشود ، بارگذاری میشوند .
public class Blog { public int BlogId { get; set; } public string Name { get; set; } public string Url { get; set; } public string Tags { get; set; } public virtual ICollection<Post> Posts { get; set; } }
غیر فعال کردن Lazy Load برای Serialization :
Lazy Load و Serialization خیلی خوب با هم ترکیب نمیشوند ، و اگر مراقب نباشید ، بخاطر فعال بودن
Lazy Loading کوئری گرفتن از کل پایگاه داده به پایان میرسد . اکثر serializers ها با انجام پردازش بر روی یک نمونه از یک نوع ، کار میکنند . مشخصه ها Lazy Loading را راه میاندازند ، بنابراین entity های بیشتری serialized میشوند .
این تمرین خوبی برای غیر فعال کردن lazy loading قبل از serialization روی یک entity است . در بخش زیر با چگونگی انجام آن آشنا خواهید شد :
غیر فعال کردن lazy loading برای یک navigation propery مشخص :
با non-virtual قرار دادن post property میتوان lazy loading یک post collection را غیر فعال کرد :
public class Blog { public int BlogId { get; set; } public string Name { get; set; } public string Url { get; set; } public string Tags { get; set; } public ICollection<Post> Posts { get; set; } }
غیر فعال کردن lazy loading برای تمام entity ها :
lazy loading میتواند برای تمام entity ها ، با قرار دادن یک flag برای Configuration property در context ، غیرفعال شود . برای مثال :
public class BloggingContext : DbContext { public BloggingContext() { this.Configuration.LazyLoadingEnabled = false; } }
Explicitly Loading :
حتی زمانی که lazy loading غیر فعال است ، هنوز امکان استفاده از lazy load برای entity های مرتبط وجود دارد ، اما این باید بوسیله فراخوانی explicit loading انجام شود . برای انجام این کار از متد load برای ورود entityهای مرتبط استفاده میکنیم . برای مثال :
using (var context = new BloggingContext()) { var post = context.Posts.Find(2); // Load the blog related to a given post context.Entry(post).Reference(p => p.Blog).Load(); // Load the blog related to a given post using a string context.Entry(post).Reference("Blog").Load(); var blog = context.Blogs.Find(1); // Load the posts related to a given blog context.Entry(blog).Collection(p => p.Posts).Load(); // Load the posts related to a given blog // using a string to specify the relationship context.Entry(blog).Collection("Posts").Load(); }
توجه داشته باشید که Reference method بهتر است زمانی استفاده شود که یک entity ، یک navigation property به یک single entity داشته باشد . از طرف دیگر ، Collection method بهتر است زمانی استفاده شود که یک entity ، یک navigation property به یک مجموعه ای از entityها داشته باشد
بکار بردن filterها در زمان استفاده از explicitly loading برای entityهای مرتبط :
Query method پردازشی را برای کوئری های اساسی فراهم میآورد که Entity Framework در زمان بارگذاری entityهای مرتبط از آنها استفاده میکند . سپس میتوانید از LINQ برای اعمال Filterها به کوئری ها ، قبل از اجرای آنها ، استفاده کنید . این کار را میتوانید با فراخوانی extension methodهایی از LINQ همانند ToList , Load و ... انجام دهید .
Query method میتواند هم با refrence و هم با collection navigation propertiyها مورد استفاده قرار گیرد . اما در صورتی که قسمتی از مجموعه را بارگذاری کند ، بیشتر برای مجموعه مفید است . برای مثال :
using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); // Load the posts with the 'entity-framework' tag related to a given blog context.Entry(blog) .Collection(b => b.Posts) .Query() .Where(p => p.Tags.Contains("entity-framework") .Load(); // Load the posts with the 'entity-framework' tag related to a given blog // using a string to specify the relationship context.Entry(blog) .Collection("Posts") .Query() .Where(p => p.Tags.Contains("entity-framework") .Load(); }
زمانی که از متد Query استفاده میکنید ، بهترین کار این است که lazy load را برای navigation propery غیر فعال کنید . چون در غیر این صورت تمام مجموعه توسط مکانیزم lazy load بارگذاری میشود .
توجه داشته باشید که relationship میتواند بجای lambda expresion تحت عنوان یک string مشخص شود ، IQueryable بازگشتی زمانی که یک رشته مورد استفاده قرار میگرد ، generic نمیباشد ، بنابراین متد cast قبل از هر چیزی نیاز است .
استفاده از Query برای شمردن related entityها بدون بارگذاری آنها :
گاهی اوقات نیاز است که بدون هزینه برای بارگذاری تمام entity ها ، از تعداد رابطه های entity با entity های دیگر در پایگاه داده مطلع شویم . متد Query با متد LINQ count برای انجام این کار میتواند مورد استفاده قرار بگیرد ، برای مثال :
using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); // Count how many posts the blog has var postCount = context.Entry(blog) .Collection(b => b.Posts) .Query() .Count(); }
- C#.net
- 5k بازدید
- 3 تشکر