Entitätstypen im BesitzOwned Entity Types

Hinweis

Dieses Feature ist neu in EF Core 2.0.This feature is new in EF Core 2.0.

EF Core können Sie die Modell-Entitätstypen, die nur für Navigationseigenschaften von anderen Entitätstypen angezeigt werden können.EF Core allows you to model entity types that can only ever appear on navigation properties of other entity types. Diese heißen Entitätstypen im Besitz.These are called owned entity types. Die Entität, die einen eigener Entitätstyp enthält, ist die Besitzer.The entity containing an owned entity type is its owner.

Explizite KonfigurationExplicit configuration

Im Besitz Entität, die Typen nicht gemäß der Konvention von EF Core im Modell enthalten sind.Owned entity types are never included by EF Core in the model by convention. Sie können die OwnsOne -Methode in der OnModelCreating oder fügen Sie den Typ mit OwnedAttribute (neu in EF Core 2.1) so konfigurieren Sie den Typ als ein eigener Typ.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.

In diesem Beispiel StreetAddress ist ein Typ ohne Identitätseigenschaft.In this example, StreetAddress is a type with no identity property. Dieser Typ wird als Eigenschaft des Typs „Order“ verwendet, um die Lieferadresse für eine bestimmte Bestellung anzugeben.It is used as a property of the Order type to specify the shipping address for a particular order.

Wir können die OwnedAttribute , dies als eine Entität im Besitz, wenn auf die verwiesen wird von einem anderen Entitätstyp behandeln:We can use the OwnedAttribute to treat it as an owned entity when referenced from another entity type:

[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; }
}

Es ist auch möglich, mit der OwnsOne -Methode in der OnModelCreating an, dass die ShippingAddress -Eigenschaft ist eine Entität im Besitz von der Order Entitätstyp und bei Bedarf zusätzliche Facetten zu konfigurieren.It is also possible to use the OwnsOne method in OnModelCreating to specify that the ShippingAddress property is an Owned Entity of the Order entity type and to configure additional facets if needed.

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

Wenn die ShippingAddress -Eigenschaft ist privat in der Order geben, können Sie die Version der Zeichenfolge die OwnsOne Methode: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");

Finden Sie unter den vollständigen Beispielprojekt für weiteren Kontext.See the full sample project for more context.

Implizite SchlüsselImplicit keys

Eigene Typen, die mit konfigurierten OwnsOne oder über eine Reference-Navigation ermittelt haben immer eine direkte Beziehung mit dem Besitzer, die aus diesem Grund nicht sie ihre eigenen Werte erforderlich, da die foreign Key-Werte eindeutig sind.Owned types configured with OwnsOne or discovered through a reference navigation always have a one-to-one relationship with the owner, therefore they don't need their own key values as the foreign key values are unique. Im vorherigen Beispiel die StreetAddress Typ muss es sich nicht um eine wichtige Eigenschaft zu definieren.In the previous example, the StreetAddress type does not need to define a key property.

Um zu verstehen, wie diese Objekte von EF Core nachverfolgt wird, ist es sinnvoll, die glauben, dass ein Primärschlüssel, als erstellt wird eine schatteneigenschaft für den eigenen Typ.In order to understand 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. Der Wert des Schlüssels für eine Instanz des eigenen Typs wird der Wert des Schlüssels für die Besitzer-Instanz identisch sein.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.

Auflistungen von eigenen TypenCollections of owned types

Hinweis

Dieses Feature ist neu in EF Core 2.2.This feature is new in EF Core 2.2.

So konfigurieren Sie eine Auflistung von Typen im Besitz OwnsMany sollte verwendet werden, OnModelCreating.To configure a collection of owned types OwnsMany should be used in OnModelCreating. Der Primärschlüssel wird jedoch nicht gemäß der Konvention konfiguriert werden, muss er explizit angegeben werden.However the primary key will not be configured by convention, so it needs to be specified explicitly. Es ist üblich, verwenden Sie einen komplexen Schlüssel für diese Art von Entitäten, die Integration des Fremdschlüssels für den Besitzer und eine weitere eindeutige Eigenschaft, die auch Schatten Status haben kann:It is common to use a complex key for these type of entities incorporating the foreign key to the owner and an additional unique property that can also be in shadow state:

modelBuilder.Entity<Distributor>().OwnsMany(p => p.ShippingCenters, a =>
{
    a.HasForeignKey("DistributorId");
    a.Property<int>("Id");
    a.HasKey("DistributorId", "Id");
});

Zuordnung, die im Besitz von Typen mit tabellenaufteilungMapping owned types with table splitting

Verwendung von relationalen eigene Datenbanken, als Konvention Verweis als Besitzer der gleichen Tabelle zugeordnet werden.When using relational databases, by convention reference owned types are mapped to the same table as the owner. Dies erfordert in der Tabelle in zwei Teilen: einige Spalten zum Speichern der Daten des Besitzers verwendet werden, und einige Spalten zum Speichern von Daten der Entität im Besitz des Benutzers verwendet werden.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. Dies ist eine Standardfunktion in tabellenaufteilung genannt.This is a common feature known as table splitting.

Tipp

Besitzer des Typen, die mit der tabellenaufteilung gespeichert sein können auf ähnliche Weise verwendet wird, wie komplexe Typen in EF 6 verwendeten werden.Owned types stored with table splitting can be used similarly to how complex types are used in EF6.

Gemäß der Konvention wird EF Core die Datenbankspalten für die Eigenschaften der eigene Entitätstyp mit dem folgenden Format benennen Navigation_OwnedEntityProperty.By convention, EF Core will name the database columns for the properties of the owned entity type following the pattern Navigation_OwnedEntityProperty. Aus diesem Grund die StreetAddress Eigenschaften werden in der Tabelle "Orders" mit dem Namen 'ShippingAddress_Street' und "ShippingAddress_City" angezeigt.Therefore the StreetAddress properties will appear in the 'Orders' table with the names 'ShippingAddress_Street' and 'ShippingAddress_City'.

Sie können den Anfügen der HasColumnName Methode, um diese Spalten umzubenennen:You can append the HasColumnName method to rename those columns:

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

Freigabe desselben Typs .NET für mehrere im Besitz des BenutzersSharing the same .NET type among multiple owned types

Ein eigener Entitätstyp möglich des gleichen Typs .NET als einem anderen eigenen Entitätstyp, daher, dass der .NET Typ möglicherweise nicht mit ausreichend, um ein eigener Typ zu identifizieren.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.

In diesen Fällen wird die Eigenschaft, die auf die Entität im Besitz des Besitzers der Definieren der Navigation des eigenen Entitätstyps.In those cases, the property pointing from the owner to the owned entity becomes the defining navigation of the owned entity type. Aus der Perspektive von EF Core ist die definierende Navigation Teil der Identität für den Typ zusammen mit der .NET-Typ.From the perspective of EF Core, the defining navigation is part of the type's identity alongside the .NET type.

Z. B. in der folgenden Klasse ShippingAddress und BillingAddress sind beide des gleichen Typs .NET StreetAddress:For example, in the following class ShippingAddress and BillingAddress are both of the same .NET type, StreetAddress:

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

Um zu verstehen, wie EF Core für überwachte Instanzen dieser Objekte unterscheiden, wird, kann es hilfreich sein zu denken, dass die definierende Navigation Teil des Schlüssels der Instanz zusammen mit dem Wert des Schlüssels des Besitzers und der .NET-Typ des eigenen Typs geworden ist.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.

Geschachtelte eigene TypenNested owned types

In diesem Beispiel OrderDetails besitzt BillingAddress und ShippingAddress, sind die StreetAddress Typen.In this example OrderDetails owns BillingAddress and ShippingAddress, which are both StreetAddress types. Dann besitzt der DetailedOrder-Typ OrderDetails.Then OrderDetails is owned by the DetailedOrder type.

public class DetailedOrder
{
    public int Id { get; set; }
    public OrderDetails OrderDetails { get; set; }
    public OrderStatus Status { get; set; }
}
public enum OrderStatus
{
    Pending,
    Shipped
}

Zusätzlich zu den geschachtelten Typen im Besitz des Benutzers ein eigener Typ kann eine reguläre Entität verweisen, kann es sein entweder der Besitzer oder eine andere Entität, solange die Entität im Besitz des Benutzers auf die abhängige Seite ist.In addition to nested owned types, an owned type can reference a regular entity, it can be either the owner or a different entity as long as the owned entity is on the dependent side. Diese Funktion legt die Entitätstypen, die abgesehen von komplexen Typen im Besitz in EF 6 fest.This capability sets owned entity types apart from complex types in EF6.

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

Es ist möglich, eine Verkettung der OwnsOne -Methode in einer fluent-Aufruf so konfigurieren Sie dieses Modell:It is possible to chain the OwnsOne method in a fluent call to configure this model:

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

Es ist auch möglich, die gleiche Sache mit OwnedAttribute sowohl OrderDetails und StreetAdress.It is also possible to achieve the same thing using OwnedAttribute on both OrderDetails and StreetAdress.

Das Speichern von eigene Typen in separaten TabellenStoring owned types in separate tables

Im Gegensatz zu EF6 komplexe Typen können auch eigene Typen in einer separaten Tabelle vom Besitzer gespeichert werden.Also unlike EF6 complex types, owned types can be stored in a separate table from the owner. Sie können einfach aufrufen, um die Konvention überschreiben, der einen eigenen Typ als Besitzer der gleichen Tabelle zugeordnet, ToTable , und geben Sie einen anderen Tabellennamen an.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. Im folgende Beispiel ordnet OrderDetails und die zwei Adressen in eine separate Tabelle von DetailedOrder:The following example will map OrderDetails and its two addresses to a separate table from DetailedOrder:

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

Abfragen von Typen im BesitzQuerying owned types

Beim Abfragen des Besitzers werden standardmäßig eigene Typen eingeschlossen.When querying the owner the owned types will be included by default. Es ist nicht erforderlich, verwenden die Include -Methode, selbst wenn Sie eigenen Typen in einer separaten Tabelle gespeichert sind.It is not necessary to use the Include method, even if the owned types are stored in a separate table. Auf der Grundlage des Modells beschrieben vor, die folgende Abfrage erhalten Order, OrderDetails und die beiden gehören StreetAddresses aus der Datenbank:Based on the model described before, the following query will get Order, OrderDetails and the two owned StreetAddresses from the database:

var order = context.DetailedOrders.First(o => o.Status == OrderStatus.Pending);
Console.WriteLine($"First pending order will ship to: {order.OrderDetails.ShippingAddress.City}");

EinschränkungenLimitations

Einige dieser Einschränkungen ist die Grundlage wie die im Besitz des Benutzers Entität Typen arbeiten, aber einige andere werden Einschränkungen, die wir in zukünftigen Versionen entfernt werden kann:Some of these limitations are fundamental to how owned entity types work, but some others are restrictions that we may be able to remove in future releases:

Standardmäßig EinschränkungenBy-design restrictions

  • Sie können nicht erstellt werden ein DbSet<T> für einen Typ im Besitz des BenutzersYou cannot create a DbSet<T> for an owned type
  • Sie können nicht aufrufen Entity<T>() mit einem Datentyp auf, die im Besitz des Benutzers ModelBuilderYou cannot call Entity<T>() with an owned type on ModelBuilder

Aktuelle MängelCurrent shortcomings

  • Vererbungshierarchien, die enthalten, das im Besitz, Entitätstypen werden nicht unterstütztInheritance hierarchies that include owned entity types are not supported
  • Referenz-Navigationen hinweg, um eigene Entitätstypen darf nicht null sein, es sei denn, sie explizit in eine separate Tabelle vom Besitzer zugeordnet sindReference navigations to owned entity types cannot be null unless they are explicitly mapped to a separate table from the owner
  • Instanzen von Entitätstypen im Besitz des Benutzers können nicht von mehreren Besitzern gemeinsam genutzt werden (Dies ist ein bekanntes Szenario für die Value-Objekte, die mithilfe von Entitätstypen im Besitz nicht implementiert werden kann.)Instances of owned entity types cannot be shared by multiple owners (this is a well-known scenario for value objects that cannot be implemented using owned entity types)

Mängel in früheren VersionenShortcomings in previous versions

  • In EF Core 2.0 gehören zu, dass die Entitätstypen können nicht in abgeleiteten Entitätstypen deklariert werden, es sei denn, die eigenen Entitäten explizit in eine separate Tabelle aus der Besitzerhierarchie zugeordnet sind.In EF Core 2.0, navigations to owned entity types cannot be declared in derived entity types unless the owned entities are explicitly mapped to a separate table from the owner hierarchy. Diese Einschränkung wurde in EF Core 2.1 entferntThis limitation has been removed in EF Core 2.1
  • In EF Core 2.0 und 2.1 nur Verweis wurden zu eigene Typen unterstützt.In EF Core 2.0 and 2.1 only reference navigations to owned types were supported. Diese Einschränkung wurde in EF Core 2.2 entferntThis limitation has been removed in EF Core 2.2