The owned entity was first introduced in EF Core 2.0, the same .NET type can be shared among different entities. Owned entities do not contain a key or identity property of their own, but would always be a navigational property of another entity.
By convention, EF Core never includes owned entity types in the model. You can annotate the type with the [Owned] attribute or use the OwnsOne method in OnModelCreating to configure the type as an owned type.
In the following example, Address is a type with no identity property. It is used as a property of the Author type to specify the address of a particular author.
public class Author
{
public int AuthorId { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
}
[Owned]
public class Address
{
public string Street { get; set; }
public string City { get; set; }
}
Here [Owned] attribute is used to treat Address as an owned entity when referenced from another entity type.
It is also possible to use the OwnsOne method in OnModelCreating to specify that the Address property is an Owned Entity of the Author entity type.
modelBuilder.Entity<Order>().OwnsOne(p => p.Address);
If the Address property is private in the Author type, you can use the string version of the OwnsOne method:
modelBuilder.Entity<Order>().OwnsOne(typeof(Address), "Address");
Owned types configured with OwnsOne or discovered through reference navigation always have a one-to-one relationship with the owner, therefore they don't need their key values as the foreign key values are unique.
Address type does not need to define a key property.When owned types are defined through a collection, it isn't enough to just create a shadow property to act as both the foreign key into the owner and the primary key of the owned instance, because there can be multiple owned type instances for each owner.
You can use OwnsMany in OnModelCreating to configure a collection of owned types. Owned types need a primary key, if there are no good candidates properties on the .NET type, EF Core can try to create one.
We have the two most straightforward solutions.
In this example, we will use the Distributor class.
public class Distributor
{
public int Id { get; set; }
public ICollection<Address> ShippingCenters { get; set; }
}
By default, the primary key used for the owned type referenced through the ShippingCenters navigation property will be ("DistributorId", "Id") where DistributorId is the FK and Id is a unique int value.
To configure a different primary key, you can call HasKey.
modelBuilder.Entity<Distributor>().OwnsMany(p => p.ShippingCenters, a =>
{
a.WithOwner().HasForeignKey("OwnerId");
a.Property<int>("Id");
a.HasKey("Id");
});