Owned Entity Types
首先owned entity type是EF Core 2.0的新特性。
至於什么是owned entity types,可以先把他理解為EF Core官方支持的值對象。
值對象
舉一個簡單的例子,你可能在開發中經常遇到,訂單,地址,地址簿的關系:
public class Order { public int Id { get; set; } public string Name { get; set; } public double Price { get; set; } public Address Address { get; set; } } public class AddressBook { public string FriendName { get; set; } public int Id { get; set; } public Address Address { get; set; } } public class Address { public string City { get; set; } public string Street { get; set; } }
這個示例里面的Address對象就是典型的值對象,他在訂單中意義是訂單地址,他在電話本里的意義是朋友的住址,就像訂單里的Name和AddressBook中FriendName一樣,你改了就改了,和其他的沒關系,不會因為你改了訂單地址就修改了電話本那個人的地址。
https://www.cnblogs.com/xishuai/p/ddd_valueobject_entityframework.html 這篇大神的文章詳細介紹了值對象在以前版本EF中的設計,現在有了Owned Entity Types,就有了官方實現。
定義
官方文檔上的定義,翻譯過來就是:EF Core 定義在model中僅用於顯示的其他實體類型Navigation properties被稱為Owned Entity types,就叫做自有實體吧,擁有自有實體的實體叫做擁有者。
下面看看怎么在EF Core中實現。
顯式配置
自有實體 在EF Core不能使用慣例方式,可以在OnModelCreating方法中使用OwnsOne方法,或者使用聲明屬性(OwnedAttribute,EF Core 2.1以上版本支持)。
[Owned]
public class Address
{
public string Street { get; set; }
public string City { get; set; }
}
modelBuilder.Entity<Order>().OwnsOne(p => p.Address);
//或者使用這種方式
modelBuilder.Entity<Order>().OwnsOne(typeof(Address), "Address");
這在EF Core中時通過影子屬性( shadow property)實現的,
自有實體集合是在EF Core 2.2中實現,可以使用OnModelCreating的OwnsMany方法實現:
modelBuilder.Entity<Distributor>().OwnsMany(p => p.ShippingCenters, a => { a.HasForeignKey("DistributorId"); a.Property<int>("Id"); a.HasKey("DistributorId", "Id"); });
數據庫
慣例情況是:Address屬性在Order表中的名字是:Address_City和Address_Street,你也可以在OwnsOne方法中使用HasColumnName自定義列名,也可以存儲到單獨的表中,下面代碼將地址存到單獨表(orderAddress)中:
modelBuilder.Entity<Order>().OwnsOne(
o => o.Address,
sa =>
{
sa.ToTable("orderAddress");
sa.Property(p => p.Street).HasColumnName("ToStreet");
sa.Property(p => p.City).HasColumnName("ToCity");
});
查詢
跟普通的屬性一樣:
var order = context.Orders.FirstOrDefault(); Console.WriteLine($"TO: {order.ShippingAddress.City}");
限制
- 不能生成自有對象的DbSet<T> 。
- 不能在ModelBuilder中使用自有對象的Entity<T>()。
即將實現:
- 自有對象不支持繼承。
- 除非在單獨的表中使用,否則自有對象不能為空。
- 多個擁有者不能使用同一個自有對象(廢話)。
以前版本存在問題:
- EF Core 2.0中除非存在獨立的表中,否則自有對象不能在派生實體類型中聲明。
- EF Core 2.0和2.1只支持指向自有對象的reference navigations ,在2.2中移除這一限制。