myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Rund um die Programmierung » DDD Aggregate + Repository Pattern in EF Core
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

DDD Aggregate + Repository Pattern in EF Core

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
munzili munzili ist männlich
myCSharp.de-Mitglied

Dabei seit: 15.10.2019
Beiträge: 1


munzili ist offline

DDD Aggregate + Repository Pattern in EF Core

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo!

Ich versuche gerade ein Projekt in DDD und Clean Architecture umzusetzen bzw. sind das meine ersten Versuche Augenzwinkern

Ich arbeite auf .Net Core 3.0 und möchte eine API bereitstellen. Dabei bin ich auf eine kleine Hürde gestoßen, wo ich jetzt nicht genau weis, wie man das am besten löst. Folgender Code ist vereinfacht um auf meine allgemeine Hürde hinzuweisen, value objects entfernt bzw vereinfacht.

Ich hab ein Domain Aggregate DistributionPackage:

C#-Code:
public class DistributionPackage
{
      private readonly List<DistributionPackageItem> _distributionPackageItems = new List<DistributionPackageItem>();

        private DistributionPackage() { }

        public DistributionPackage(/*...*/)
        {
            Id = Guid.NewGuid();
            // ...
            Date = DateTime.Now;
        }

        public Guid Id { get; private set; }

        public DateTime Date { get; private set; }

        public IReadOnlyCollection<DistributionPackageItem> DistributionPackageItems => _distributionPackageItems.AsReadOnly();

        public DistributionPackageItem AddItem(string name, string description, int amount)
        {
            var newItem = new DistributionPackageItem(name, description, amount);
            _distributionPackageItems.Add(newItem);
            return newItem;
        }
}

public class DistributionPackageItem
{
        private DistributionPackageItem() { }

        internal DistributionPackageItem(string name, string description, int amount)
        {
            Id = Guid.NewGuid();
            Name = name;
            Description = description;
            Amount = amount;
        }

        public Guid Id { get; private set; }

        public string Name { get; private set; }

        public string Description { get; private set; }

        public int Amount { get; private set; }
}

Von EF Core sieht meine Config so aus:

C#-Code:
public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext (DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }

        public DbSet<DistributionPackage> DistributionPackage { get; set; }

        // ...

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            // Customer Aggreagte
            modelBuilder.Entity<DistributionPackage>(ConfigureDistributionPackage);
            modelBuilder.Entity<DistributionPackageItem>(ConfigureDistributionPackageItem);

            // ....
        }

        private void ConfigureDistributionPackage(EntityTypeBuilder<DistributionPackage> builder)
        {
            builder.HasKey(distributionPackage => distributionPackage.Id);
            builder.HasMany(distributionPackage => distributionPackage.DistributionPackageItems).WithOne().Metadata.PrincipalToDependent.SetPropertyAccessMode(PropertyAccessMode.Field);
        }

        private void ConfigureDistributionPackageItem(EntityTypeBuilder<DistributionPackageItem> builder)
        {
            builder.HasKey(distributionPackageItem => distributionPackageItem.Id);
        }
}

Wenn ich jetzt versuche ein DistributionPackage zu erstellen in meinen UseCases, items hinzufüge und diese in der DB mittels einer Repository classe speichere, funktioniert alles wunderbar.

C#-Code:
repository.Add(distributionPackage());}

repository.Add macht nichts anderes als

C#-Code:
            _dbContext.Set<DistributionPackage>().Add(entity);

Das ganze klappt auch ohne Probleme. Wenn ich aber jetzt das Objekt mit weiteren Items fülle und Updaten will via _dbContext.SaveChangesAsync(); bekomme ich einen Fehler, das ein Objekt versucht wird zu speichern, das nicht in der Db existiert (weil ja das Item in AddItem() erstellt wird und nicht registriert im EF)

Meine Frage nun: Wie löss ich das am besten ohne jetzt das Aggregate aufzubohren?

- In jedem UseCase via Repository Interface die items manuel registrieren lassen? Hört sich für mich sehr unsauber an
- Irgentwie im Infrastrucuture.Data Layer versuchen AddItem via Domain Events abzufangen und registrieren zu lassen?
- Im Infrastrucuture.Data Layer versuchen die AddItem zu overloaden und im Repository by Add() abzufangen?
- Besser vorschlgäe oder elegantere Lösungsansätze?

Besten Danke!
Neuer Beitrag 15.10.2019 18:32 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 13.063
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Das Domain Model stellt keine Datenbank-Entität dar (was für alle Datenbank-Konzepte gilt, nicht nur EF).
Verwendest Du das DDD Modell als Entität ist das eine Verletzung der Schichtentrennung.
Basics:  [Artikel] Drei-Schichten-Architektur

Konzepte in EF (vor allem wenns Richtung Optimierung dessen geht) machen dann eine reine DDD Umsetzung schwierig bzw. komplex - und umgekehrt.
Im Endeffekt die Gegenfrage: wie ernst und streng willst Du Dich an den Konzepten orientieren - und mit welchen Kompromissen kannst Du leben.

Zitat:
Im Infrastrucuture.Data Layer

Da solltest Du evtl nochmal schauen, wie man Namespaces schneidet :-)

Zitat:
Besser vorschlgäe oder elegantere Lösungsansätze?

Dafür gibt es zu wenig Infos von Deiner Seite. Ein Repository Ansatz ist weit verbreitet - es gibt aber auch viele weitere Ansätze (zB Event Sourcing).
Neuer Beitrag 15.10.2019 18:48 Beiträge des Benutzers | zu Buddylist hinzufügen
Alf Ator
myCSharp.de-Mitglied

avatar-586.gif


Dabei seit: 30.10.2007
Beiträge: 589
Entwicklungsumgebung: VS2005 / VS2008


Alf Ator ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von munzili:
Meine Frage nun: Wie löss ich das am besten ohne jetzt das Aggregate aufzubohren?

- In jedem UseCase via Repository Interface die items manuel registrieren lassen? Hört sich für mich sehr unsauber an
- Irgentwie im Infrastrucuture.Data Layer versuchen AddItem via Domain Events abzufangen und registrieren zu lassen?
- Im Infrastrucuture.Data Layer versuchen die AddItem zu overloaden und im Repository by Add() abzufangen?
- Besser vorschlgäe oder elegantere Lösungsansätze?

Alles wesentliche hat Abt schon gesagt.

Ich habe festgestellt, dass die Auswahl des richtigen Weges zu stark von der Anforderung abhängig ist, als dass man sich auf einen Festlegen könnte.
Grade Beispiel-Implementierungen und Test-Projekte geben die nötige Komplexität für tiefergehendes Verständnis nicht her.
Neuer Beitrag Gestern, 13:53 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum
Antwort erstellen


© Copyright 2003-2019 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 18.10.2019 08:21