Laden...

Hirarchische Datenstruktur über EntityFramework oder Services

Erstellt von kleinrechner vor 3 Jahren Letzter Beitrag vor 3 Jahren 284 Views
K
kleinrechner Themenstarter:in
16 Beiträge seit 2018
vor 3 Jahren
Hirarchische Datenstruktur über EntityFramework oder Services

Hallo,
da ich gerade dabei bin die Sturkur unserer Anwendung etwas zu überarbeiten, bin ich aktuell am überlegen, was hier die beste Vorgehenweise ist.

  • .net Framework 4.8
  • Entity Framework 6.1

Ich habe eine Datenstrukur, mit einer 1-n Verknüpfung zwischen den jeweiligen Tabellen Checklist->Category->Item. Die Checkliste enthält eine Liste aller zugehörigen Kategorien usw.
Für jede Tabelle existiert ein entsprechender Service, zum Auslesen, Speichern usw der Daten in der Datenbank.

Wenn ich eine Checkliste auslese, sollten alle Unterelemente enthalten sein.
Dies kann ich mithilfe von Navigations-Properties und EntityFramework über Include erreichen oder ich rufe jeweils die Methode des Service auf.
Welche Methode würdet ihr hier verwenden, was ist BestPractice? Ist die Service-Methode nicht deutlich langsamer?

cu
Christian

16.835 Beiträge seit 2008
vor 3 Jahren

Für jede Tabelle existiert ein entsprechender Service, zum Auslesen, Speichern usw der Daten in der Datenbank. Was ist hier ein Service? Ein Implementierungspattern oder reden wir von Microservice?
Wenn es sich um ein Microservice im eigentlichen Sinne handelt, dann ist das eine Verletzung der Vorgehensweise, da sich zwei Microservices niemals die gleiche Datenbank teilen sollen.

Dank Architektur mit Hirarchie und Berechtigung hab ich nun gesehen, dass Du von einer Implementierung sprichst.
Nein, ein Service ist ein Logik-Einheit und kennt den Datenbank-Aufbau nicht.
Es gibt daher nicht zwangweise für jede Tabelle einen Service.

Aber: es gibt für jede Tabelle ein Repository.
Dieses hat die Aufgabe von Lesen, Schreiben, Speichern. Das ist nicht Aufgabe vom Service.
Der Service sagt "wann" gespeichert wird (SaveChanges) aber nicht wie.

Wenn man Services zu klein schneidet, dann hilft das am Ende auch nicht.

Dies kann ich mithilfe von Navigations-Properties und EntityFramework über Include erreichen

Include braucht man gar nicht; damit lädst Du am Ende vom Tag viel zu viele Informationen, weil Du im aller aller seltestens Fall wirklich alle Entitäten in der vollen Breite brauchst.

Besser ist nur das zu laden, was Du brauchst, und das geht sehr einfach über Projektionen und gilt hier als Best Practise.
Eine Hilfestellung dazu bietet AutoMapper mit der ProjectTo Methode. Verwende ich auch in alle möglichen Konstellationen.

public Task<T?> GetAccountProjection<T>(int userId, CancellationToken ct) where T : class
    => QueryUsers(DbTrackingOptions.Disabled)
        .Where(UserAccountQuery.HasId(id))
        .ProjectTo<T?>(_mapper.ConfigurationProvider) <<<<<
        .SingleOrDefaultAsync(ct);

UserEMailContactProjection? sender = await _userRepository
    .GetAccountProjection<UserEMailContactProjection>(userId, ct).ConfigureAwaitFalse();

Welche Methode würdet ihr hier verwenden, was ist BestPractice? Ist die Service-Methode nicht deutlich langsamer? Musst sagen, was die Service Methode ist. Ein Microservice soll man ja nicht direkt von Außen ansprechen, sondern über Gateways.
Ja, der Call auf ein Microservice ist i.d.R. langsamer als direkt auf die DB - aber das ist ein Nachteil, den man aufgrund der enormen Vorteile in Kauf nimmt.

Dein Service ist hier falsch implementiert, weil Du offenbar damit auch Datenbank-Operationen darstellst; weniger Logik.
Es ist absolut okay, wenn Du für lesende Operationen direkt auf das Repository zugreifst - aber lade nur die notwendigen Dinge. Anbei ein Bild wie der Zugriff durchaus erlaubt ist (siehe auch [Artikel] Drei-Schichten-Architektur)

"Langsamer" ist hier aber eine Einheit, die vermutlich nicht im relevanten Bereich liegt.