دوره آموزشی Entity FrameWork Core - قسمت 29
فقط یک گزاره پرس و جو(query predicate) است که برای پرس و جوهای موجودیت هایی که این ویژگی برای آنها فعال شده است، به انتهای عبارت Where اضافه می شود.
فیلترهای Global query، معمولاً در OnModelCreating برای entity typeها اعمال می شوند. EF Core چنین فیلترهایی را به طور خودکار برای هر LINQ queries مربوط به آنentity type اعمال می کند.
خوب ابتدا و قبل از آنکه وارد بحث اصلی خود شویم بیایید مفتهیم بالا را باهم مرور کنیم :
مثال زیر نحوه استفاده از فیلترهای Global query را برای پیاده سازی رفتارهای پرس و جوی Soft delete و Multi-tenancy در یک blogging model ساده نشان می دهد.
ابتدا موجودیت ها را تعریف می کنیم:
public class Blog { #pragma warning disable IDE0051, CS0169 // Remove unused private members private string _tenantId; #pragma warning restore IDE0051, CS0169 // Remove unused private members public int BlogId { get; set; } public string Name { get; set; } public string Url { get; set; } public List<Post> Posts { get; set; } } public class Post { public int PostId { get; set; } public string Title { get; set; } public string Content { get; set; } public bool IsDeleted { get; set; } public Blog Blog { get; set; } }
به اعلام فیلد tenantId_ در موجودیت Blog توجه کنید. این فیلد برای مرتبط کردن هر نمونه Blog با یک tenant خاص استفاده خواهد شد.همچنین یک پراپرتی IsDeleted در موجودیت Post تعریف شده است. این ویژگی برای پیگیری اینکه آیا یک نمونه پست "soft delete" شده است یا خیر استفاده می شود. به این معنی که نمونه بدون حذف فیزیکی دادهها، حذف شده علامتگذاری میشود.
سپس، فیلترهای پرس و جو را در OnModelCreating با استفاده از HasQueryFilter API پیکربندی کنید.
modelBuilder.Entity<Blog>().HasQueryFilter(b => EF.Property<string>(b, "_tenantId") == _tenantId); modelBuilder.Entity<Post>().HasQueryFilter(p => !p.IsDeleted);
از این به بعد فیلترها به طور خودکار برای هر درخواست LINQ برای آن entity type اعمال می شود.
در حال حاضر نمی توان چندین فیلتر پرس و جو را روی یک موجودیت تعریف کرد - فقط آخرین فیلتر اعمال خواهد شد. با این حال، می توانید با استفاده از عملگر AND منطقی (&& در سی شارپ) یک فیلتر واحد با شرایط چندگانه تعریف کنید.
می توانید از navigation در تعریف فیلترهای global query استفاده کنید. استفاده از navigation در فیلتر پرس و جو باعث می شود که فیلترهای پرس و جو به صورت بازگشتی اعمال شوند. هنگامی که EF Core navigation های مورد استفاده در فیلترهای پرس و جو را گسترش میدهد، فیلترهای پرس و جوی تعریف شده بر روی موجودیتهای ارجاعشده را نیز اعمال میکند.
توجه داشته باشید استفاده از required navigation برای دسترسی به موجودیتیکه دارای فیلترهای global query تعریف شده است ممکن است منجر به نتایج غیرمنتظره(unexpected results) شود.
این پیکربندی در OnModelCreating به صورت زیر خواهد بود:
modelBuilder.Entity<Blog>().HasMany(b => b.Posts).WithOne(p => p.Blog); modelBuilder.Entity<Blog>().HasQueryFilter(b => b.Posts.Count > 0); modelBuilder.Entity<Post>().HasQueryFilter(p => p.Title.Contains("fish"));
در مرحله بعد:
var filteredBlogs = db.Blogs.ToList();
این پرس و جو SQL زیر را تولید می کند که فیلترهای پرس و جو تعریف شده برای هر دو موجودیت بلاگ و پست را اعمال می کند:
SELECT [b].[BlogId], [b].[Name], [b].[Url] FROM [Blogs] AS [b] WHERE ( SELECT COUNT(*) FROM [Posts] AS [p] WHERE ([p].[Title] LIKE N'%fish%') AND ([b].[BlogId] = [p].[BlogId])) > 0
در حال حاضر EF Core چرخهها را در تعاریف فیلتر global query تشخیص نمیدهد، بنابراین هنگام تعریف آنها باید مراقب باشید. چرخه ها می توانند به حلقه های بی نهایت در طول ترجمه پرس و جو منجر شوند.
فیلترها ممکن است با استفاده از عملگر IgnoreQueryFilters برای queryهای جداگانه LINQ غیرفعال شوند.
blogs = db.Blogs .Include(b => b.Posts) .IgnoreQueryFilters() .ToList();
فیلترهای global query را فقط می توان برای root Entity Type یک inheritance hierarchy تعریف کرد.
بیشتر بخوانید : دوره آموزشی Entity FrameWork Core - قسمت 31
بیشتر بخوانید : دوره آموزشی Entity FrameWork Core
بیشتر بخوانید : نقشه راه توسعه دهندگان Asp.NET Core