
یادگیری سی شارپ از مفاهیم پایه تا پروژه محور: شیگرایی، کار با SQL و LINQ، ORMها (Entity Framework)، ساخت پروژه مدیریت رستوران با گزارشات حرفهای و امکانات کامل!
مشاهده بیشتر
یادگیری MVC Core از مبانی تا پیشرفته: شیگرایی، Routing، Entity Framework، امنیت، تست یونیت، Razor، Ajax، و پروژههای کاربردی! یک دوره کامل برای تسلط بر توسعه وب با ASP.NET Core. به صورت حضوری و آنلاین!
مشاهده بیشترمشخصات مقاله
آموزش Query زدن روی Data Base با استفاده از EF Core
آموزش Query زدن روی Data Base با استفاده از EF Core
Query زدن در EF Core درست مثل EF 6 است، با این تفاوت که بهینه تر شده و می توان توابع C#/VB.NET را در LINQ-to-Entities query ها استفاده کرد.
بخش LINQ-to-Entities را برای مطالعه ی بیشتر درمورد اصول Query زدن در Entity Framework ببینید.
در این بخش با قابلیت های جدید query زدن در EF Core آشنا می شوید.
توابع C#/VB.NET در query ها
EF Core قابلیت جدیدی در LINQ-to-Entities ارائه می دهد که می توان توابع C# یا VB.NET را درون query قرار داد. این قابلیت در EF 6 نبود.
1 2 3 4 5 6 7 8 9 10 11 | private static void Main(string[] args) { var context = new SchoolContext(); var studentsWithSameName = context.Students .Where(s => s.FirstName == GetName()) .ToList(); } public static string GetName() { return "Bill"; } < button ></ button > |
در L2E بالا، تابع GetName() را درون عبارت Where قرار داده ایم. Quey زیر در Data Base اجرا می شود:
1 2 3 4 5 6 | exec sp_executesql N'SELECT [s].[StudentId], [s].[DoB], [s].[FirstName], [s].[GradeId], [s].[LastName], [s].[MiddleName] FROM [Students] AS [s] WHERE [s].[FirstName] = @__GetName_0',N'@__GetName_0 nvarchar(4000)', @__GetName_0=N'Bill' Go< button ></ button > |
Eager Loading
EF Core از Eager Loading موجودیت های وابسته پشتیبانی می کند. مثل EF 6، با استفاده از Include() و projection query می توان این کار را انجام داد. علاوه بر این، ThenInclude() extension method را نیز برای laod چندین سطح دیتای وابسته ارائه می کند. (EF 6 متد ThenInclude() را پشتیبانی نمی کند).
Include
برخلاف EF 6، می توان از lambda expression به عنوان پارامتر برای متد Include() برای تعیین یک navigation property به صورت زیر استفاده کرد:
1 2 3 4 5 | var context = new SchoolContext(); var studentWithGrade = context.Students .Where(s => s.FirstName == "Bill") .Include(s => s.Grade) .FirstOrDefault();< button ></ button > |
در مثال بالا، .Include(s => s.Grade) یک lambda expression به صورت s => s.Grade برای تعیین property که باید با موجودیت Student از Data Base در یک Query واکشی شود، استفاده شده است.
1 2 3 4 5 | SELECT TOP(1) [s].[StudentId], [s].[DoB], [s].[FirstName], [s].[GradeId],[s].[LastName], [s].[MiddleName], [s.Grade].[GradeId], [s.Grade].[GradeName], [s.Grade].[Section] FROM [Students] AS [s] LEFT JOIN [Grades] AS [s.Grade] ON [s].[GradeId] = [s.Grade].[GradeId] WHERE [s].[FirstName] = N'Bill'< button ></ button > |
می توان نام property را به شکل string در متد Include() تعیین کرد، مثل EF 6:
1 2 3 4 5 6 | var context = new SchoolContext(); var studentWithGrade = context.Students .Where(s => s.FirstName == "Bill") .Include("Grade") .FirstOrDefault(); < button ></ button > |
مثال بالا توصیه نمی شود، چرا که اگر نام property اشتباه نوشته شود یا موجود نباشد، runtime exception خواهید گرفت. همیشه از متد Include() با یک lambda expression استفاده کنید، که خطا در زمان کامپایل شناسایی شود.
می توان پس از متد FromSql()، متد Include() extension method را فراخوانی کرد:
1 2 3 4 5 6 | var context = new SchoolContext(); var studentWithGrade = context.Students .FromSql("Select * from Students where FirstName ='Bill'") .Include(s => s.Grade) .FirstOrDefault(); < button ></ button > |
توجه کنید: متد Include() را نمی توان پس از متد DbSet.Find() صدا زد، مثلا ()context.Students.Find(1).Include در EF Core 2.0 قابل استفاده نیست. ممکن است در نسخه های آینده این قابلیت ممکن شود.
استفاده از چند Include
می توانید از متد Include() چندین بار برای واکشی navigation property های متعدد یک entity استفاده کرد. برای مثال، کد زیر موجودیت های Grade و StudentCourses را برای Student، واکشی می کند:
1 2 3 4 5 6 | var context = new SchoolContext(); var studentWithGrade = context.Students.Where(s => s.FirstName == "Bill") .Include(s => s.Grade) .Include(s => s.StudentCourses) .FirstOrDefault(); < button ></ button > |
Query بالا، دو SQL Query را در یک round trip به Data Base اجرا می کند:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | SELECT TOP(1) [s].[StudentId], [s].[DoB], [s].[FirstName], [s].[GradeId], [s].[LastName], [s].[MiddleName], [s.Grade].[GradeId], [s.Grade].[GradeName], [s.Grade].[Section] FROM [Students] AS [s] LEFT JOIN [Grades] AS [s.Grade] ON [s].[GradeId] = [s.Grade].[GradeId] WHERE [s].[FirstName] = N'Bill' ORDER BY [s].[StudentId] Go SELECT [s.StudentCourses].[StudentId], [s.StudentCourses].[CourseId] FROM [StudentCourses] AS [s.StudentCourses] INNER JOIN ( SELECT DISTINCT [t].* FROM ( SELECT TOP(1) [s0].[StudentId] FROM [Students] AS [s0] LEFT JOIN [Grades] AS [s.Grade0] ON [s0].[GradeId] = [s.Grade0].[GradeId] WHERE [s0].[FirstName] = N'Bill' ORDER BY [s0].[StudentId] ) AS [t] ) AS [t0] ON [s.StudentCourses].[StudentId] = [t0].[StudentId] ORDER BY [t0].[StudentId] < button ></ button > |
متد ThenInclude
EF Core این extension method جدید را معرفی کرده که برای واکشی چندین سطح از موجودیت های مرتبط استفاده می شود. مثال زیر را در نظر بگیرید:
1 2 3 4 5 6 | var context = new SchoolContext(); var student = context.Students.Where(s => s.FirstName == "Bill") .Include(s => s.Grade) .ThenInclude(g => g.Teachers) .FirstOrDefault(); < button ></ button > |
در این مثال، بخش (Include(s => s.Grade. باعث load شدن Grade (که یک navigation property است) در موجودیت Student می شود.
بخش(ThenInclude(g => g.Teachers. باعث load شدن Teacher که یک collection property برای موجودیت Grade است، می شود. متد ThenInclude باید بعد از متد Include فراخوانی شود. کد بالا دستور زیر را در Data Base اجرا می کند.
Projection Query
می توانیم برای load چند entity مرتبط به هم به جای Include() و ThenInclude() از projection query ها استفاده کنیم. مثال بعد نحوه استفاده از projection query برای load موجودیت های Student، Grade و Teacher نشان می دهد.
1 2 3 4 5 6 7 8 9 10 | var context = new SchoolContext(); var stud = context.Students.Where(s => s.FirstName == "Bill") .Select(s => new { Student = s, Grade = s.Grade, GradeTeachers = s.Grade.Teachers }) .FirstOrDefault(); < button ></ button > |
در مثال بالا، متد .Select extension method برای include کردن موجودیت های Student، Grade و Teacher در نتیجه استفاده شده است. این کد SQL Query مشابه مثال متد ThenInclude() تولید می کند.
Lazy Loading
Lazy Loading در EF Core 2.0 پشتیبانی نمی شود. می توانید issue مربوط به lazy loading در Github را دنبال کنید.
Explicit Loading
Explicit Loading به همان شیوه مشابه در EF 6 کار می کند. در این بخش از آموزش بیشتر به آن می پردازیم.