دوره آموزشی Entity FrameWork Core - قسمت بیستم

دوره آموزشی Entity FrameWork Core - قسمت نوزدهم پیشنهاد می کنم قبل از شروع موضوع اصلی مقدمه ای را باهم مرور کنیممفهوم سازنده ها(constructors) در سی شارپ :سازنده متد خاصی است که نام آن با نام کلاس یکی است. سازنده به دلایل زیر خاص است:سازنده نوع بازگشتی را ندارد.هنگام ایجاد یک شی جدید، کامپایلر #C، به طور خودکار سازنده را فراخوانی می کند.به طور معمول، شما از یک سازنده برای مقداردهی اولیه شی جدید با تخصیص مقادیر به پراپرتی های شی استفاده می کنید.کامپایلر C# هنگام تعریف کلاس به طور ضمنی یک سازنده بدون هیچ پارامتری(parameterless constructor) ایجاد می کند. برای درک این موضوع مثال زیر را در نظر بگیرید :// Person.cs class Person { }سی شارپ به طور ضمنی یک سازنده بدون هیچ پارامتری مانند زیر ایجاد می کند:// Person.cs class Person { public Person() { } }مثال زیر نشان می دهد که چگونه #C به طور ضمنی سازنده را هنگام ایجاد یک شی جدید فراخوانی می کند:// Program.cs Person p1 = new();Output:Create a new Person objectتعریف یک constructor :مثال زیر یک سازنده با سه پارامتر برای کلاس Person تعریف می کند:// Person.cs class Person { private string firstName; private string lastName; private byte age; public Person(string firstName, string lastName, byte age) { this.firstName = firstName; this.lastName = lastName; this.age = age; } public string GetFullName() { return $&quot{this.firstName} {this.lastName}&quot } }در این مثال سازنده سه آرگومان را می پذیرد و private پراپرتی های firstName، lastName و age را مقداردهی اولیه می کند.هنگامی که به طور صریح یک سازنده تعریف می کنید، کامپایلر #C دیگر به صورت ضمنی سازنده بدون پارامتر را به کلاس اضافه نمی کند.بنابراین، برای ایجاد یک شیء جدید Person، باید سه آرگومان مانند زیر را ارسال کنید// Program.cs var p1 = new Person(&quotJohn&quot, &quotDoe&quot, 25);و یا :Person p2 = new(&quotJohn&quot, &quotDoe&quot, 25);تعریف چند constructor برای یک کلاس:سی شارپ به شما امکان می دهد چندین سازنده با پارامترهای مختلف برای یک کلاس تعریف کنید. مثلا:// Person.cs class Person { private string firstName; private string lastName; private byte age; public Person() { } public Person(string firstName, string lastName) { this.firstName = firstName; this.lastName = lastName; } public Person(string firstName, string lastName, byte age) { this.firstName = firstName; this.lastName = lastName; this.age = age; } }در این مثال، کلاس Person دارای سه سازنده است.سازنده اول یک سازنده بدون پارامتر است که هیچ پارامتری را نمی پذیرد.سازنده دوم دو پارامتر را می پذیرد و خصوصیات firstName و lastName را مقداردهی اولیه می کند.سازنده سوم سه پارامتر را می پذیرد و ویژگی های firstName، lastName و age را مقداردهی اولیه می کند.با انجام این کار، می توانید با ارسال هیچ پارامتر، دو پارامتر یا سه پارامتر به سازنده های مربوطه، یک Personobject جدید ایجاد کنید:// Program.cs var p1 = new Person(); var p2 = new Person(&quotJohn&quot, &quotDoe&quot); var p3 = new Person(&quotJohn&quot, &quotDoe&quot, 25);برای انعطاف پذیری بیشتر برای مقداردهی اولیه یک شی جدید می‌توانید یک سازنده را در سازنده دیگری فراخوانی کنید، همانطور که در مثال زیر نشان داده شده است: // Person.cs class Person { private string firstName; private string lastName; private byte age; public Person() { Console.WriteLine(&quotInitialized the object&quot); } public Person(string firstName, string lastName) : this() { this.firstName = firstName; this.lastName = lastName; Console.WriteLine(&quotInitialized the first name & last name properties&quot); } public Person(string firstName, string lastName, byte age) : this(firstName, lastName) { this.age = age; Console.WriteLine(&quotInitialized the age property&quot); } }در این مثال، سازنده دوم، سازنده اول را از طریق این کلمه کلیدی this فراخوانی می کند:public Person(string firstName, string lastName) : this()هنگامی که یک شی با دو پارامتر ایجاد می کنید، این سازنده سازنده بدون پارامتر را قبل از اجرای بدنه آن فراخوانی می کند.سازنده سوم سازنده دوم را از طریق این کلمه کلیدی با آرگومان های firstName و lastName فراخوانی می کند:public Person(string firstName, string lastName, byte age) : this(firstName, lastName)اگر یک شی جدید با سه آرگومان ایجاد کنید، سازنده سوم سازنده دوم را فراخوانی می کند که سازنده اول را فراخوانی می کند.بنابراین، سازنده ها به ترتیب زیر اجرا می شوند:public Person() public Person(string firstName, string lastName) : this() public Person(string firstName, string lastName, byte age) : this(firstName, lastName)با انجام این کار، می توانید از منطق سازنده های دیگر هنگام مقداردهی اولیه اشیاء استفاده مجدد کنید.لازم نیست همه پراپرتی ها دارای پارامترهای سازنده باشند. به عنوان مثال کلاس person می تواند دارای propertyای باشد که توسط هیچ پارامتر سازنده ای تنظیم نشده است، بنابراین EF Core آن را پس از فراخوانی سازنده به روش عادی تنظیم می کند.توجه داشته باشید EF Core نمی تواند ویژگی های ناوبری (navigation properties) را با استفاده از سازنده تنظیم کند.خلاصه از مطالب مقدماتی :سازنده سی شارپ متد خاصی است که نام آن با نام کلاس یکی است.کامپایلر سی شارپ به طور خودکار سازنده را هنگام ایجاد یک شی جدید فراخوانی می کند.از سازنده ها برای مقداردهی اولیه اشیا استفاده کنید.از سازنده های متعدد در یک کلاس برای انعطاف پذیری بیشتر برای مقداردهی اولیه یک شی جدید استفاده کنید.خوب حال بیایید به سراغ موضوع اصلی برویم : Entity types with constructors :پارامترهای سازنده را می‌توان به ویژگی‌های نگاشت شده(mapped properties) یا به انواع مختلفی از سرویس‌ها برای تسهیل رفتارهایی مانند بارگذاری تنبل(lazy-loading) متصل کرد.سازنده می تواند public, private یا هر گونه دسترسی دیگری باشد. با این حال، پراکسی‌های بارگذاری تنبل (lazy-loading proxies) مستلزم این هستند که سازنده از inheriting proxy class قابل دسترسی باشد. معمولاً این به معنای public یا protected آن است.هنگامی که propertyها از طریق سازنده مقداردهی می شوند، منطقی است که برخی از آنها فقط خواندنی(Read-only properties) باشند. EF Core از این پشتیبانی می کند، اما مواردی وجود دارد که باید به آنها توجه کرد:پراپرتی های بدون setter بر اساس قرارداد map نمی شوند. ( propertyهایی که نباید map شوند، مانند computed properties)استفاده از مقادیر کلیدی تولید شده به طور خودکار(automatically generated key values) نیاز به یک ویژگی کلیدی دارد که خواندن و نوشتن است، زیرا هنگام درج موجودیت های جدید، مقدار کلید باید توسط key generator تنظیم شود.یک راه آسان برای جلوگیری از این موارد استفاده از private setters است. مثلا:public class Blog { public Blog(int id, string name, string author) { Id = id; Name = name; Author = author; } public int Id { get; private set; } public string Name { get; private set; } public string Author { get; private set; } public ICollection<Post> Posts { get; } = new List<Post>(); } public class Post { public Post(int id, string title, DateTime postedOn) { Id = id; Title = title; PostedOn = postedOn } public int Id { get; private set; } public string Title { get; private set; } public string Content { get; set; } public DateTime PostedOn { get; private set; } public Blog Blog { get; set; } }خوب حالا EF Core یک پراپرتی با private setters را به عنوان خواندن و نوشتن می بیند، به این معنی که همه پراپرتی ها مانند قبل نگاشت می شوند و key همچنان می تواند توسط پایگاه داده تولید شود.یک راه جایگزین به جای استفاده از private setters این است که پراپرتی ها را واقعاً فقط خواندنی قرار دهید و نگاشت واضح‌تر را در OnModelCreating اضافه کنید. به همین ترتیب، برخی از ویژگی ها را می توان به طور کامل حذف کرد و تنها با فیلدها جایگزین کرد. به عنوان مثال، این انواع موجودیت را در نظر بگیرید:public class Blog { private int _id; public Blog(string name, string author) { Name = name; Author = author; } public string Name { get; } public string Author { get; } public ICollection<Post> Posts { get; } = new List<Post>(); } public class Post { private int _id; public Post(string title, DateTime postedOn) { Title = title; PostedOn = postedOn; } public string Title { get; } public string Content { get; set; } public DateTime PostedOn { get; } public Blog Blog { get; set; } }و این پیکربندی در OnModelCreating:protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>( b => { b.HasKey(&quot_id&quot); b.Property(e => e.Author); b.Property(e => e.Name); }); modelBuilder.Entity<Post>( b => { b.HasKey(&quot_id&quot); b.Property(e => e.Title); b.Property(e => e.PostedOn); }); }موارد قابل توجه: پراپرتی key اکنون یک فیلد است. این یک فیلد فقط خواندنی نیست تا بتوان از کلیدهای تولید شده(generated keys ) در data store استفاده کرد.سایر پراپرتی ها، ویژگی های فقط خواندنی هستند که فقط در سازنده تنظیم شده اند.اگر مقدار کلید اولیه فقط توسط EF تنظیم شود یا از پایگاه داده خوانده شود، دیگر نیازی به گنجاندن آن در سازنده نیست. این باعث می‌شود که پراپرتی key به عنوان یک فیلد ساده باقی بماند و روشن می‌شود که هنگام ایجاد blogها یا postهای جدید نباید به طور صریح تنظیم شود.تزریق سرویس ها(Injecting services) :خوب EF Core همچنین می‌تواند «سرویس‌ها» را به سازنده یک موجودیت تزریق کند. به عنوان مثال، موارد زیر را می توان تزریق کرد:DbContextILazyLoaderAction<object, string>IEntityTypeبه عنوان مثال، یک DbContext تزریق شده می تواند برای دسترسی انتخابی به پایگاه داده برای به دست آوردن اطلاعات در مورد موجودیت های مرتبط بدون بارگیری همه آنها استفاده شود. در مثال زیر از این برای به دست آوردن تعداد postهای یک blog بدون بارگیری post ها استفاده می شود:public class Blog { public Blog() { } private BloggingContext Context { get; set; } private Blog(BloggingContext context) { Context = context; } public int Id { get; set; } public string Name { get; set; } public string Author { get; set; } public ICollection<Post> Posts { get; set; } public int PostsCount => Posts?.Count ?? Context?.Set<Post>().Count(p => Id == EF.Property<int?>(p, &quotBlogId&quot)) ?? 0; } public class Post { public int Id { get; set; } public string Title { get; set; } public string Content { get; set; } public DateTime PostedOn { get; set; } public Blog Blog { get; set; } }تزریق DbContext به این شکل اغلب یک ضد الگو(anti-pattern) در نظر گرفته می شود زیرا entity type ها شما را مستقیماً با EF Core جفت(couples) می کند. بیشتر بخوانید : دوره آموزشی Entity FrameWork Core - قسمت 21بیشتر بخوانید : دوره آموزشی Entity FrameWork Coreبیشتر بخوانید : نقشه راه توسعه دهندگان Asp.NET Corehttps://zarinp.al/farshidazizi