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");
});