Types d’entités appartenant àOwned Entity Types

Note

Cette fonctionnalité est une nouveauté dans EF Core 2.0.This feature is new in EF Core 2.0.

EF Core vous permet de types d’entités de modèle qui peuvent apparaître uniquement sur les propriétés de navigation d’autres types d’entités.EF Core allows you to model entity types that can only ever appear on navigation properties of other entity types. Ils sont appelés détenus des types d’entités.These are called owned entity types. Est de l’entité qui contient un type d’entité appartenant à son propriétaire.The entity containing an owned entity type is its owner.

Configuration expliciteExplicit configuration

La propriété entité types sont jamais inclus par cœur de EF dans le modèle par convention.Owned entity types are never included by EF Core in the model by convention. Vous pouvez utiliser la OwnsOne méthode dans OnModelCreating ou annotez le type avec OwnedAttribute (nouveau dans EF Core 2.1) pour configurer le type comme un type lui appartenant.You can use the OwnsOne method in OnModelCreating or annotate the type with OwnedAttribute (new in EF Core 2.1) to configure the type as an owned type.

Dans cet exemple, StreetAddress est un type avec aucune propriété d’identité.In this example, StreetAddress is a type with no identity property. Il est utilisé comme propriété du type Order pour spécifier l’adresse d’expédition d’une commande particulière.It is used as a property of the Order type to specify the shipping address for a particular order. Dans OnModelCreating, nous utilisons le OwnsOne méthode pour spécifier que la propriété ShippingAddress est une entité propriétaire du type de commande.In OnModelCreating, we use the OwnsOne method to specify that the ShippingAddress property is an Owned Entity of the Order type.

public class StreetAddress
{
    public string Street { get; set; }
    public string City { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public StreetAddress ShippingAddress { get; set; }
}

// OnModelCreating
modelBuilder.Entity<Order>().OwnsOne(p => p.ShippingAddress);

Si la propriété ShippingAddress est privée dans le type de commande, vous pouvez utiliser la version de chaîne de la OwnsOne méthode :If the ShippingAddress property is private in the Order type, you can use the string version of the OwnsOne method:

modelBuilder.Entity<Order>().OwnsOne(typeof(StreetAddress), "ShippingAddress");

Dans cet exemple, nous utilisons le OwnedAttribute pour obtenir le même objectif :In this example, we use the OwnedAttribute to achieve the same goal:

[Owned]
public class StreetAddress
{
    public string Street { get; set; }
    public string City { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public StreetAddress ShippingAddress { get; set; }
}

Clés implicitesImplicit keys

Dans EF Core 2.0 et 2.1, seules les propriétés de navigation de référence peuvent pointer vers appartenant à des types.In EF Core 2.0 and 2.1, only reference navigation properties can point to owned types. Collections de types détenus ne sont pas pris en charge.Collections of owned types are not supported. La propriété référence de ces types ont toujours le type de relation avec le propriétaire, par conséquent, leurs valeurs de clé n’est nécessaire.These reference owned types always have a one-to-one relationship with the owner, therefore they don't need their own key values. Dans l’exemple précédent, le type StreetAddress n’a pas besoin de définir une propriété de clé.In the previous example, the StreetAddress type does not need to define a key property.

Pour comprendre comment EF Core effectue le suivi de ces objets, il est utile de considérer qu’une clé primaire est créée comme un shadow, propriété pour le type de lui appartenant.In order to understanding how EF Core tracks these objects, it is useful to think that a primary key is created as a shadow property for the owned type. La valeur de la clé d’une instance du type détenue sera identique à la valeur de la clé de l’instance de propriétaire.The value of the key of an instance of the owned type will be the same as the value of the key of the owner instance.

Propriété types avec fractionnement de la table de mappageMapping owned types with table splitting

Lorsque vous utilisez des bases de données relationnelles, par convention détenue types sont mappés à la même table en tant que le propriétaire.When using relational databases, by convention owned types are mapped to the same table as the owner. Cela nécessite de fractionnement de la table en deux : certaines colonnes permet de stocker les données du propriétaire, et certaines colonnes permet de stocker des données de l’entité détenue.This requires splitting the table in two: some columns will be used to store the data of the owner, and some columns will be used to store data of the owned entity. Il s’agit d’une fonctionnalité courante connue en tant que le fractionnement de la table.This is a common feature known as table splitting.

Conseil

Détenus stockés avec le fractionnement de la table de types peuvent être utilisées similaire aux types de complexité dans EF6.Owned types stored with table splitting can be used very similarly to how complex types are used in EF6.

Par convention, EF Core nommera les colonnes de la base de données pour les propriétés du type d’entité appartenant à suivre le modèle de EntityProperty_OwnedEntityProperty.By convention, EF Core will name the database columns for the properties of the owned entity type following the pattern EntityProperty_OwnedEntityProperty. Par conséquent, les propriétés de StreetAddress s’affichent dans la table Orders avec les noms ShippingAddress_Street et ShippingAddress_City.Therefore the StreetAddress properties will appear in the Orders table with the names ShippingAddress_Street and ShippingAddress_City.

Vous pouvez ajouter la HasColumnName méthode pour renommer ces colonnes.You can append the HasColumnName method to rename those columns. Dans le cas où StreetAddress est une propriété publique, les mappages seraitIn the case where StreetAddress is a public property, the mappings would be

modelBuilder.Entity<Order>().OwnsOne(
    o => o.ShippingAddress,
    sa =>
        {
            sa.Property(p=>p.Street).HasColumnName("ShipsToStreet");
            sa.Property(p=>p.City).HasColumnName("ShipsToCity");
        });

Partage le même type .NET entre plusieurs types d’enfantsSharing the same .NET type among multiple owned types

Un type d’entité détenue peut être du même type .NET en tant que type d’entité appartenant à un autre, par conséquent, le type .NET peuvent ne pas suffire pour identifier un type lui appartenant.An owned entity type can be of the same .NET type as another owned entity type, therefore the .NET type may not be enough to identify an owned type.

Dans ce cas, la propriété pointez auprès du directeur de l’entité appartenant à devient le définition navigation du type d’entité détenue.In those cases, the property pointing from the owner to the owned entity becomes the defining navigation of the owned entity type. Du point de vue du noyau de EF, le volet de navigation définition fait partie de l’identité du type en même temps que le type .NET.From the perspective of EF Core, the defining navigation is part of the type's identity alongside the .NET type.

Par exemple, dans la classe suivante, ShippingAddress et BillingAddress sont du même type .NET, StreetAddress :For example, in the following class, ShippingAddress and BillingAddress are both of the same .NET type, StreetAddress:

public class Order
{
    public int Id { get; set; }
    public StreetAddress ShippingAddress { get; set; }
    public StreetAddress BillingAddress { get; set; }
}

Afin de comprendre comment EF Core permet de distinguer les marques d’instances de ces objets, il peut être utile de considérer que la définition de la navigation est devenue partie de la clé de l’instance en même temps que la valeur de la clé du propriétaire et le type .NET du type détenu.In order to understand how EF Core will distinguish tracked instances of these objects, it may be useful to think that the defining navigation has become part of the key of the instance alongside the value of the key of the owner and the .NET type of the owned type.

Appartenant à des types imbriquésNested owned types

Dans cet exemple OrderDetails possède BillingAddress et ShippingAddress, qui sont des types StreetAddress.In this example OrderDetails owns BillingAddress and ShippingAddress, which are both StreetAddress types. Puis OrderDetails est détenue par le type de commande.Then OrderDetails is owned by the Order type.

public class Order
{
    public int Id { get; set; }
    public OrderDetails OrderDetails { get; set; }
    public OrderStatus Status { get; set; }
}

public class OrderDetails
{
    public StreetAddress BillingAddress { get; set; }
    public StreetAddress ShippingAddress { get; set; }
}

public class StreetAddress
{
    public string Street { get; set; }
    public string City { get; set; }
}

Il est possible de chaîne de la OwnsOne méthode dans un mappage fluent pour configurer ce modèle :It is possible to chain the OwnsOne method in a fluent mapping to configure this model:

modelBuilder.Entity<Order>().OwnsOne(p => p.OrderDetails, od =>
    {
        od.OwnsOne(c => c.BillingAddress);
        od.OwnsOne(c => c.ShippingAddress);
    });

Il est possible de réaliser la même chose à l’aide OwnedAttribute sur OrderDetails et StreetAdress.It is possible to achieve the same thing using OwnedAttribute on both OrderDetails and StreetAdress.

En plus des types imbriqués détenus, un type détenu peut référencer une entité normale.In addition to nested owned types, an owned type can reference a regular entity. Dans l’exemple suivant, le pays est une entité normale (c'est-à-dire sans propriétaire) :In the following example, Country is a regular (i.e. non-owned) entity:

public class StreetAddress
{
    public string Street { get; set; }
    public string City { get; set; }
    public Country Country { get; set; }
}

Cette fonctionnalité définit les types d’entité détenue indépendamment des types complexes dans EF6.This capability sets owned entity types apart from complex types in EF6.

Le stockage des types détenus dans des tables distinctesStoring owned types in separate tables

Plus à la différence des types complexes EF6, appartenant à des types peuvent être stockés dans une table distincte du propriétaire.Also unlike EF6 complex types, owned types can be stored in a separate table from the owner. Pour remplacer la convention qui mappe un type appartenant à la même table que le propriétaire, vous pouvez simplement appeler ToTable et fournir un autre nom de table.In order to override the convention that maps an owned type to the same table as the owner, you can simply call ToTable and provide a different table name. L’exemple suivant mappera OrderDetails et ses deux adresses dans une table distincte à partir de la commande :The following example will map OrderDetails and its two addresses to a separate table from Order:

modelBuilder.Entity<Order>().OwnsOne(p => p.OrderDetails, od =>
    {
        od.OwnsOne(c => c.BillingAddress);
        od.OwnsOne(c => c.ShippingAddress);
    }).ToTable("OrderDetails");

Interrogation appartenant à des typesQuerying owned types

Quand le propriétaire fait l’objet d’une interrogation, les types détenus sont inclus par défaut.When querying the owner the owned types will be included by default. Il n’est pas nécessaire d’utiliser le Include (méthode), même si les types détenus sont stockés dans une table distincte.It is not necessary to use the Include method, even if the owned types are stored in a separate table. Selon le modèle décrit précédemment, la requête suivante extrait ordre, OrderDetails et le StreeAddresses appartenant à deux pour toutes les commandes en attente à partir de la base de données :Based on the model described before, the following query will pull Order, OrderDetails and the two owned StreeAddresses for all pending orders from the database:

var orders = context.Orders.Where(o => o.Status == OrderStatus.Pending);

LimitationsLimitations

Voici quelques limitations des types d’entité détenue.Here are some limitations of owned entity types. Certaines de ces limitations sont fondamentaux pour comment détenue travail de types, mais que d’autres est point-à-temps restrictions que nous souhaiterions à supprimer dans les futures versions :Some of these limitations are fundamental to how owned types work, but some others are point-in-time restrictions that we would like to remove in future releases:

Défauts en coursCurrent shortcomings

  • L’héritage des types détenus n’est pas pris en charge.Inheritance of owned types is not supported
  • Appartenant à des types ne peuvent pas être pointés par une propriété de navigation de collectionOwned types cannot be pointed at by a collection navigation property
  • Dans la mesure où ils utilisent le fractionnement de table par défaut détenus types présentent également les restrictions suivantes, sauf si explicitement mappées à une autre table :Since they use table splitting by default owned types also have the following restrictions unless explicitly mapped to a different table:
    • Ils ne peuvent pas être détenus par un type dérivéThey cannot be owned by a derived type
    • La propriété de navigation définition ne peut pas être définie avec la valeur null (c'est-à-dire appartenant types sur la même table sont toujours requis)The defining navigation property cannot be set to null (i.e. owned types on the same table are always required)

Restrictions de par sa conceptionBy-design restrictions

  • Vous ne pouvez pas créer un DbSet<T>You cannot create a DbSet<T>
  • Vous ne pouvez pas appeler Entity<T>() avec un type détenu sur ModelBuilderYou cannot call Entity<T>() with an owned type on ModelBuilder