من با ویژگی بسیار خوبی از Entity Framework Core مواجه شدم که می خواهم آن را با شما به اشتراک بگذارم. انواع متعلق به آن است.
انواع متعلق به EF Core به شما امکان می دهد فیلدهایی را که نمی خواهید به عنوان مرجع نشان داده شوند، در یک نوع جداگانه گروه بندی کنید.
اجازه دهید با یک مثال شروع کنیم. فرض کنید شما این مدل را دارید. شما مشتری و سفارش دارید و هر دو فیلدهایی برای آدرس دارند.
- class Customer
- {
- [Key]
- public long CustomerID { get; set; }
- public string Name { get; set; }
- public string Street { get; set; }
- public string City { get; set; }
- public string State { get; set; }
- }
- class Order
- {
- [Key]
- public long OrderID { get; set; }
- public bool IsShipped { get; set; }
- public string Street { get; set; }
- public string City { get; set; }
- public string State { get; set; }
- }
شما به راحتی می توانید با استخراج فیلدهای آدرس در جدول جدید و ارجاع به آن جدول در جداول مشتری و سفارش، مدل قبلی را تغییر دهید.
- class Address
- {
- [Key]
- public long AddressID { get; set; }
- public string Street { get; set; }
- public string City { get; set; }
- public string State { get; set; }
- }
اما اگر بخواهید سه فیلد آدرس را در داخل Customer و Order نگه دارید، و بخواهید کد را اصلاح کنید و پیچیدگی و تکراری بودن را کاهش دهید، چه کاری انجام می دهید؟ پاسخ در نهادهای تحت مالکیت است.
می توانید کلاس Address خود را به روز کنید و فیلد کلید آن را حذف کنید و یک مرجع را در Customer and Order به شرح زیر بگنجانید.
- class Address
- {
- public string Street { get; set; }
- public string City { get; set; }
- public string State { get; set; }
- }
- class Customer
- {
- [Key]
- public long CustomerID { get; set; }
- public string Name { get; set; }
- public Address Address { get; set; }
- }
- class Order
- {
- [Key]
- public long OrderID { get; set; }
- public bool IsShipped { get; set; }
- public Address Address { get; set; }
- }
تمام شده؟ نه هنوز. شما نمی توانید کد خود را به این صورت بگذارید زیرا هیچ موجودیتی بدون کلید اصلی قابل تعریف نیست. در واقع، اگر بخواهید تغییرات خود را در پایگاه داده اعمال کنید، با این خطا مواجه خواهید شد.
![](http://pezhvak24.ir/dl/codenevis/firstcode/article/reducing-complexity-using-entity-framework-core-owned-types/Images/owning%20types%20no%20id.png)
به روز رسانی بعدی که باید انجام دهیم در خود زمینه داده است. ما میتوانیم از Fluent API برای نشان دادن نحوه عملکرد مدل خود استفاده کنیم.
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- base.OnModelCreating(modelBuilder);
- modelBuilder.Entity().OwnsOne(a => a.Address);
- modelBuilder.Entity().OwnsOne(a => a.Address);
- }
اکنون می توانیم مدل خود را در پایگاه داده اعمال کنیم و شاهد وقوع جادو باشیم!
![](http://pezhvak24.ir/dl/codenevis/firstcode/article/reducing-complexity-using-entity-framework-core-owned-types/Images/owning%20types%20update%201.png)
به روز رسانی ما بسیار امیدوار کننده به نظر می رسد. با این حال، ما در اینجا مشکل بسیار کمی داریم، هیچ کس آن پیشوندهای "Address_" را دوست ندارد!
پاسخ دوباره در Fluent API است.
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- base.OnModelCreating(modelBuilder);
- modelBuilder.Entity().OwnsOne(a => a.Address, add=>
- {
- add.Property(p => p.Street).HasColumnName(nameof(Address.Street));
- add.Property(p => p.City).HasColumnName(nameof(Address.City));
- add.Property(p => p.State).HasColumnName(nameof(Address.State));
- });
- modelBuilder.Entity().OwnsOne(a => a.Address);
- }
پس از اعمال کد قبلی، می توانید تفاوت بین دو جدول تولید شده را مشاهده کنید.
![](http://pezhvak24.ir/dl/codenevis/firstcode/article/reducing-complexity-using-entity-framework-core-owned-types/Images/owning%20types%20update%202.png)
نکته کوچکی که باید به آن اشاره کرد این است که میتوانید با استفاده از روش نادیده گرفتن یک فرم ویژگی که نگاشت شده است را حذف کنید.
- add.Ignore(p => p.State);
و اگر رویکرد Fluent API را دوست ندارید، میتوانید به سادگی کلاس Address را با ویژگی OwnedAttribute تزئین کنید، با این حال، این به شما اجازه نمیدهد نام فیلدها و ویژگیهای دیگر را سفارشی کنید.
- [Owned]
- class Address
- {
- public string Street { get; set; }
- public string City { get; set; }
- public string State { get; set; }
- }
نکته دیگری که باید به آن اشاره کرد این است که می توانید با استفاده از روش ToTable یک جدول برای موجودیت متعلق به خود ایجاد کنید:
- modelBuilder.Entity().OwnsOne(a => a.Address, add=>
- {
- add.Property(p => p.Street).HasColumnName(nameof(Address.Street));
- add.Property(p => p.City).HasColumnName(nameof(Address.City));
- add.Property(p => p.State).HasColumnName(nameof(Address.State));
- add.ToTable("CustomerAddress");
- });
و این یک رابطه یک به یک بین مشتری و CustomerAddress ایجاد شده جدید ایجاد می کند.
![](http://pezhvak24.ir/dl/codenevis/firstcode/article/reducing-complexity-using-entity-framework-core-owned-types/Images/owning%20types%20update%203.png)
نکته آخر در اینجا این است که می توانید با استفاده از روش OwnsMany یک رابطه یک به چند ایجاد کنید.
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- base.OnModelCreating(modelBuilder);
- modelBuilder.Entity().OwnsMany(a => a.Address);
- modelBuilder.Entity().OwnsOne(a => a.Address);
- }
همچنین باید نهاد مشتری را برای مطابقت با رابطه یک به چند به روز کنید:
- class Customer
- {
- [Key]
- public long CustomerID { get; set; }
- public string Name { get; set; }
- public List
Address { get; set; } - }
نتیجه به شرح زیر است،
![](http://pezhvak24.ir/dl/codenevis/firstcode/article/reducing-complexity-using-entity-framework-core-owned-types/Images/owning%20types%20update%204.png)