ASP.NET Core 1.0 (formerly ASP.NET 5) provides a revamped Web development framework geared towards the requirements of modern Web applications. The new framework, currently in RC1, requires you to learn many new concepts not found in ASP.NET MVC 5. To that end, this article enumerates a few important features that ASP.NET MVC 5 developers should know as they prepare to learn this new framework.
یکی از مزایای مهم استفاده از Entity framework، خواص راهبری (navigation properties) آن هستند که امکان تهیه کوئریهای بین جداول را به سادگی و به نحوی منطقی فراهم میکنند.
برای مثال دو جدول شهرها و افراد را درنظر بگیرید. مقصود از تعریف جدول شهرها در اینجا، مشخص سازی محل تولد افراد است:
در ادامه این کلاسها را در معرض دید EF Code first قرار داده:
و همچنین تعدادی رکورد آغازین را نیز به جداول مرتبط اضافه میکنیم:
در این حالت برای نمایش لیست نام افراد به همراه محل تولد آنها، بنابر روال سابق SQL نویسی، نوشتن کوئری LINQ زیر بسیار متداول است:
که حاصل آن اجرای کوئری ذیل بر روی بانک اطلاعاتی خواهد بود:
این نوع کوئریهای join دار را به نحو سادهتری نیز میتوان در EF با استفاده از خواص راهبری و بدون join نویسی مستقیم تهیه کرد:
که دقیقا همان خروجی SQL یاد شده را تولید میکند.
مثال دوم:
میخواهیم لیست شهرها را بر اساس تعداد کاربر متناظر به صورت نزولی مرتب کنیم:
همانطور که مشاهده میکنید از خواص راهبری در قسمت order by هم میشود استفاده کرد. خروجی SQL کوئری فوق به صورت زیر است:
مثال سوم:
در ادامه قصد داریم لیست شهرها را به همراه تعداد نفرات متناظر با آنها نمایش دهیم:
در اینجا از خاصیت راهبری People برای شمارش تعداد اعضای متناظر با هر شهر استفاده شده است.
خروجی SQL کوئری فوق به نحو ذیل است:
برای مثال دو جدول شهرها و افراد را درنظر بگیرید. مقصود از تعریف جدول شهرها در اینجا، مشخص سازی محل تولد افراد است:
public class Person { public int Id { get; set; } public string Name { get; set; } [ForeignKey("BornInCityId")] public virtual City BornInCity { get; set; } public int BornInCityId { get; set; } } public class City { public int Id { get; set; } public string Name { get; set; } public virtual ICollection<Person> People { get; set; } }
public class MyContext : DbContext { public DbSet<City> Cities { get; set; } public DbSet<Person> People { get; set; } }
و همچنین تعدادی رکورد آغازین را نیز به جداول مرتبط اضافه میکنیم:
public class Configuration : DbMigrationsConfiguration<MyContext> { public Configuration() { AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = true; } protected override void Seed(MyContext context) { var city1 = new City { Name = "city-1" }; var city2 = new City { Name = "city-2" }; context.Cities.Add(city1); context.Cities.Add(city2); var person1 = new Person { Name = "user-1", BornInCity = city1 }; var person2 = new Person { Name = "user-2", BornInCity = city1 }; context.People.Add(person1); context.People.Add(person2); base.Seed(context); } }
public static class Test { public static void RunTests() { Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Configuration>()); using (var context = new MyContext()) { var peopleAndCitiesList = from person in context.People join city in context.Cities on person.BornInCityId equals city.Id select new { PersonName = person.Name, CityName = city.Name }; foreach (var item in peopleAndCitiesList) { Console.WriteLine("{0}:{1}", item.PersonName, item.CityName); } } } }
SELECT [Extent1].[BornInCityId] AS [BornInCityId], [Extent1].[Name] AS [Name], [Extent2].[Name] AS [Name1] FROM [dbo].[People] AS [Extent1] INNER JOIN [dbo].[Cities] AS [Extent2] ON [Extent1].[BornInCityId] = [Extent2].[Id]
var peopleAndCitiesList = context.People .Select(person => new { PersonName = person.Name, CityName = person.BornInCity.Name });
مثال دوم:
میخواهیم لیست شهرها را بر اساس تعداد کاربر متناظر به صورت نزولی مرتب کنیم:
var citiesList = context.Cities.OrderByDescending(x => x.People.Count()); foreach (var item in citiesList) { Console.WriteLine("{0}", item.Name); }
SELECT [Project1].[Id] AS [Id], [Project1].[Name] AS [Name] FROM ( SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name], (SELECT COUNT(1) AS [A1] FROM [dbo].[People] AS [Extent2] WHERE [Extent1].[Id] = [Extent2].[BornInCityId]) AS [C1] FROM [dbo].[Cities] AS [Extent1] ) AS [Project1] ORDER BY [Project1].[C1] DESC
مثال سوم:
در ادامه قصد داریم لیست شهرها را به همراه تعداد نفرات متناظر با آنها نمایش دهیم:
var peopleAndCitiesList = context.Cities .Select(city => new { InUseCount = city.People.Count(), CityName = city.Name }); foreach (var item in peopleAndCitiesList) { Console.WriteLine("{0}:{1}", item.CityName, item.InUseCount); }
خروجی SQL کوئری فوق به نحو ذیل است:
SELECT [Extent1].[Id] AS [Id], (SELECT COUNT(1) AS [A1] FROM [dbo].[People] AS [Extent2] WHERE [Extent1].[Id] = [Extent2].[BornInCityId]) AS [C1], [Extent1].[Name] AS [Name] FROM [dbo].[Cities] AS [Extent1]
نظرات مطالب
EF Code First #7
- قرار دادن تمام کلاسهای شرکت کننده در تشکیل جداول، حالت پیش فرض و معمول است. از این جهت که برای ثبت اطلاعات جداگانه در هر کدام نیاز به DbSet متناظر خواهد بود.
+ EF توانایی یافتن روابط و تشکیل جداول متناظر را بر اساس روابط بین کلاسها، دارا است. اگر به تصویر اسکیمای حاصل دقت کنید این مساله مشهود است.
- در کل در این «مثال» ذکر دو مورد جهت برآوردن مقصود توضیحات داده شده کافی بوده.
+ EF توانایی یافتن روابط و تشکیل جداول متناظر را بر اساس روابط بین کلاسها، دارا است. اگر به تصویر اسکیمای حاصل دقت کنید این مساله مشهود است.
- در کل در این «مثال» ذکر دو مورد جهت برآوردن مقصود توضیحات داده شده کافی بوده.
اشتراکها
ASP.NET Core به زبان ساده
اگر بخواهیم اولین رکورد از یک جدول را توسط EF درخواست نماییم از متد Firstیا FirstOrDefault استفاده میشود. برای مثال واکشی اولین رکورد از جدول Student به صورت زیر است:
var student=context.Students.FirstOrDefault();
حال اگر بخواهید به جای اولین رکورد آخرین رکورد را واکشی نمایید چطور؟ برای یافتن آخرین رکورد در لیستها ی Generic و کلا لیستهای Enumerable از متد LastOrDefault استفاده میشود. با این حال این متد توسط Entity Framework پشتیبانی نمیشود و در صورتی که از کد زیر استفاده کنید برنامه با خطا متوقف خواهد شد:
var student=context.Students.LastOrDefault();
روش اول: میتوان خروجی را ابتدا به یک نوع Enumerable مانند List تبدیل کرد و سپس از متد LastOrDefault استفاده کرد. کد زیر را در نظر بگیرید:
var student=context.Students.ToList().LastOrDefault();
روش دوم: با توجه به اینکه تنها به یک رکورد (آخرین رکورد) نیاز داریم بهتر است یک رکورد هم واکشی شود. در این روش برای اینکه بتوان به آخرین رکورد رسید ابتدا رکوردهای جدول را به صورت نزولی مرتب میکنیم و سپس از متد FirstOrDefault برای واکشی آخرین رکورد استفاده مینمایید. برای مثال:
var student=context.Students.OrderByDescending(s=>s.Id).FirstOrDefault();
A jQuery plugin for extracting the dominant color from images and applying the color to their parent. Demo