[Owned] und [ComplexType] Datentypen sind fortgeschrittene Konzepte in Entity Framework Core, die es Entwicklern ermöglichen, komplexe Datentypen innerhalb von Entitäten zu verwalten. Diese Funktion erleichtert das Design von Datenmodellen und fördert Wiederverwendbarkeit und Modularität.
Die Verwendung von [Owned] und [ComplexType] Datentypen in Entity Framework Core verbessert die Effizienz und Wartbarkeit von Datenmodellen. Sie ermöglichen es, komplexe Datentypen innerhalb von Entitäten zu strukturieren, wodurch wiederverwendbare und klar definierte Modelle entstehen. Ein Vorteil ist, dass diese Datentypen automatisch mit der übergeordneten Entität geladen werden und nicht explizit mit der .Include
-Methode eingeschlossen werden müssen.
Die Zielgruppe sind Softwareentwickler und Architekten, die mit .NET und Entity Framework Core arbeiten und nach fortgeschrittenen Techniken suchen, um ihre Datenmodelle zu optimieren. Besonders profitieren Entwickler, die große und komplexe Anwendungen erstellen, bei denen Modularität und Wiederverwendbarkeit von Datenmodellen entscheidend sind.
Ein [Owned] und [ComplexType] Datentyp ist eine komplexe Datenstruktur, die einer Entität zugeordnet ist und nicht eigenständig existiert. Ein häufiges Beispiel ist eine Adresse, die als Teil einer Bestellung oder eines Distributors modelliert wird.
1[Owned]
2public class StreetAddress
3{
4 public string? Street { get; set; }
5 public string? City { get; set; }
6}
1public class Order
2{
3 public int Id { get; set; }
4 public string? Name { get; set; }
5 public StreetAddress? ShippingAddress { get; set; }
6 public StreetAddress? BillingAddress { get; set; }
7}
8
9protected override void OnModelCreating(ModelBuilder modelBuilder)
10{
11 // Owned Demo
12 modelBuilder.Entity<Order>()
13 .OwnsOne(p => p.ShippingAddress, od =>
14 {
15 od.ToTable("OrderShippingsAddress");
16 });
17}
In diesem Beispiel wurde die ShippingAddress als eigene Tabelle über den DbContext definiert, während die BillingAddress nicht separat behandelt wurde.
Ein weiteres Beispiel ist ein Distributor, der mehrere Versandzentren hat:
1public class Distributor
2{
3 public int Id { get; set; }
4 public string? Name { get; set; }
5 public StreetAddress? HeadquarterAddress { get; set; }
6 public ICollection<StreetAddress> ShippingCenters { get; set; }
7
8 public Distributor()
9 {
10 ShippingCenters = new List<StreetAddress>();
11 HeadquarterAddress = new StreetAddress();
12 }
13}
Hier werden die ShippingCenters automatisch als separate Tabelle implementiert, ohne explizite Konfigurationen im DbContext.
1[ComplexType]
2public class Address
3{
4 public string Street { get; set; }
5 public string City { get; set; }
6 public string State { get; set; }
7 public string PostalCode { get; set; }
8}
1public class Person
2{
3 public int Id { get; set; }
4 public string FirstName { get; set; }
5 public string LastName { get; set; }
6 public Address HomeAddress { get; set; }
7 public Address DeliveryAddress { get; set; }
8
9 public Person()
10 {
11 HomeAddress = new Address();
12 DeliveryAddress = new Address();
13 }
14}
15
16protected override void OnModelCreating(ModelBuilder modelBuilder)
17{
18 // Owned Demo
19 modelBuilder.Entity<Person>()
20 .OwnsOne(p => p.HomeAddress, od =>
21 {
22 od.ToTable("PeopleHomeAddress");
23 });
24}
Hier wurde die HomeAddress als separate Tabelle über den DbContext definiert, während die DeliveryAddress nicht.
.Include
eingeschlossen werden.Begrenzte Flexibilität: [Owned] Datentypen können nicht unabhängig von ihrer übergeordneten Entität gespeichert werden. Ein Fehler tritt auf, wenn versucht wird, einen Owned-Datentyp ohne die zugehörige Entität zu speichern.
Beide Konzepte fördern Modularität und Wiederverwendbarkeit, indem sie wiederverwendbare Datentypen definieren und innerhalb von Entitäten nutzen.