Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Repositories und Dependency Injection
Ahrimaan
myCSharp.de - Member



Dabei seit:
Beiträge: 363
Herkunft: Thorn

Themenstarter:

Repositories und Dependency Injection

beantworten | zitieren | melden

verwendetes Datenbanksystem: <NHibernate>

Hallo zusammen,

ich "streite" mich gerade ein wenig mit meinem Kollegen:

Er, ehemaliger Delphi Progger, kennt sowas wie Repository und DI nur Theoretisch ;-) .

So nun zum Streitthema : Ich habe ein Interface IRepository<T> also generisch.
Dieses Interface nutze ich als Contract für meine anderen Repositories.
Um die Repositories in meine Anwendung zu Injecten lagere ich die Entität des Repositories (also das <T> zB UserModel) in andere Assemblys aus um diese später nutzen zu können.
Er sagt, er würde die Entität aber in das jeweilige Repository mit einbinden.

zB die Assembly UserRepository enthält die Entität User

Nur : Habe ich dann ja wieder den harten Verweis auf das Repository und das will ich ja verhindern.
Ich gebe ihm aber recht, dass ein Verweis auf dieEntität auch nicht soo toll ist, aber zur Zeit fällt mir keine andere Lösung ein.

Wer ist also näher an der Wahrheit ?

Grüße
private Nachricht | Beiträge des Benutzers
Sarc
myCSharp.de - Member



Dabei seit:
Beiträge: 426

beantworten | zitieren | melden

Hallo,

ich sehe irgendwie den Zusammenhang zum DI nicht. Es geht dir doch rein
um die Aufteilung der Klassen in Assemblies oder hab ich das falsch verstanden?
Für ein DI ist es ja egal in welcher Assembly die jeweilige Komponente liegt.
private Nachricht | Beiträge des Benutzers
Ahrimaan
myCSharp.de - Member



Dabei seit:
Beiträge: 363
Herkunft: Thorn

Themenstarter:

beantworten | zitieren | melden

naja es geht hier darum :

Klasse A braucht IRepository<Person>

Das IRepository soll nun per DI Injected werden.

Variante A : Ich habe die Entität im PersonRepository
Dann MUSS Klasse A ein Verweis auf PersonRepository haben, damit es klappt
DI wäre dann auch realtiv witzlos

Variante B: Ich habe die Entität in einer eigenen Assembly
Dann MUSS Klasse A nur den Verweis auf die Entität haben, nicht auf das Repository selbst
DI macht wieder Sinn

Grüße
private Nachricht | Beiträge des Benutzers
Sarc
myCSharp.de - Member



Dabei seit:
Beiträge: 426

beantworten | zitieren | melden

Mit Verweis auf PersonRepository meinst du den Verweis auf die Assembly in der PersonRepository definiert ist oder?
Wichtig ist letztendlich nur, dass du in der Klasse A die Abhängigkeit zu einer Schnittstelle (in dem Fall IRepository<Person>) und nicht zu einer konkreten Implementierung hast.
In welcher Assembly die spätere konkrete Implementierung dafür dann liegt, ist aus meiner Sicht nicht so wichtig.
private Nachricht | Beiträge des Benutzers
Ahrimaan
myCSharp.de - Member



Dabei seit:
Beiträge: 363
Herkunft: Thorn

Themenstarter:

beantworten | zitieren | melden

Hi Sarc, ja in einer Assembly

Also sehe ich das Richtig, dass ich dann ein generische IRepository Injecte und nur die Entität als fester Verweis angegeben wird.

Gut Danke :-)
private Nachricht | Beiträge des Benutzers
gfoidl
myCSharp.de - Team

Avatar #avatar-2894.jpg


Dabei seit:
Beiträge: 7561
Herkunft: Waidring

beantworten | zitieren | melden

Hallo Ahrimaan,

Person ist Bestandteil des (Daten-) Model und hat im DAL nicht direkt was zu suchen. Der DAL - sprich hier das Repository - kann es kennen, aber deklariert sollte es im Model-Namespace (und ev. Model-Assembly) sein.

Ein Verweis bezieht sich immer auf eine konkrete Instanz, hier geht aber um den Typparameter des generischen Repositories.

Insofern ist mir nicht klar was ihr (du und ein Kollege) mit Verweis und Einbinden meint.


mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
private Nachricht | Beiträge des Benutzers
Ahrimaan
myCSharp.de - Member



Dabei seit:
Beiträge: 363
Herkunft: Thorn

Themenstarter:

beantworten | zitieren | melden

Hi Gü,
Zitat
Person ist Bestandteil des (Daten-) Model und hat im DAL nicht direkt was zu suchen. Der DAL - sprich hier das Repository - kann es kennen, aber deklariert sollte es im Model-Namespace (und ev. Model-Assembly) sein.

Genau darum ging es. Mein kollege ist der Meinung das Datenmodel MUSS in den DAL rein , ich sage es ist nicht so.

Damit hast du meine Aussage bekräftigt. Danke :-)

Grüße
private Nachricht | Beiträge des Benutzers
Peter Bucher
myCSharp.de - Experte

Avatar #jVxXe7MDBPAimxdX3em3.jpg


Dabei seit:
Beiträge: 6141
Herkunft: Zentralschweiz

beantworten | zitieren | melden

Hallo zusammen

@gfoidl
Ich nehme an, dass Ahrimaan mit "Verweis" eine harte Assemblyreferenz meint, die ja bei irgendeiner Typabhängigkeit - ob als Typargument oder wegen der Nutzung für eine Instanz - immer vorhanden ist.

@Ahrimaan
Rein theoretisch kannst du alles in einer Assembly haben, komplett alles.
Auch dann hat DI noch alle Vorteile (bis auf die Austauschbarkeit der Implementation ohne Neukompilierung).

Der Vorteil ist, dass du die Abhängigkeit vom konkreten Typen gelöst hast und die konkreten Typen zentral konfigurieren kannst, durch ein Austausch an einer Stelle.

Aber das halte ich nicht für sinnvoll, wie gfoidl sagt, sollte die Assembly-Aufteilung logisch sein und Solution-interne Abhängigkeiten minimieren. Wie feinkörnig ist dann wieder eine andere Entscheidung.

Der einzige zusätzliche Vorteil, wenn du bspw. die Interfaces und Implementierungen für die Repositories nicht in einer Assembly hast - und das ist die Voraussetzung dafür, also:

- Project.Data.Interfaces

- Project.Data.Sql
- Project.Data.Xml

ist die Austauschbarkeit der Implementation, ohne das du irgendetwas neu kompilieren musst, nur per Registrationsänderung in einer Xml-Datei.

Nur wenn du das brauchst, macht es Sinn, keine harten Referenzen zu haben und die Assemblies feinkörnig aufzuteilen.

Meistens braucht es dies nicht und die Nachteile, die diese Vorgehensweise mit sich zieht, sind grösser als die Vorteile.
Zitat
Mein kollege ist der Meinung das Datenmodel MUSS in den DAL rein , ich sage es ist nicht so.
Wenn du nicht feinkörnige Assembly-Unterteilungen machst, kannst du die Entities / Models in deine DAL-Assembly packen. Wenn feinkörniger, gehören diese zumindest logisch zusammen. Das ergibt sich auch aus der mindestens weichen, wenn nicht harten Referenz.

Was versteht er unter "DAL"?
Eine Assembly? Eine logische Zusammenhörigkeit?


Gruss Peter
--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

- https://peterbucher.ch/ - Meine persönliche Seite
- https://fpvspots.net/ - Spots für FPV Dronenflüge
private Nachricht | Beiträge des Benutzers
Ahrimaan
myCSharp.de - Member



Dabei seit:
Beiträge: 363
Herkunft: Thorn

Themenstarter:

beantworten | zitieren | melden

Hi Peter,

mein Kollege meint mit DAL schon eine Assembly, welche den Datzenzugriff regelt.
Zitat
Rein theoretisch kannst du alles in einer Assembly haben, komplett alles.
Auch dann hat DI noch alle Vorteile (bis auf die Austauschbarkeit der Implementation ohne Neukompilierung).
Das verstehe ich aber nicht so recht : Wenn ich eh eine Konkrete Implementierung in eine Assembly packe, muss ich ja nicht mehr zwingend gegen das interface schreiben, sondern kann direkt auf die Implementation zugreifen, da ich die Assembly ja eh eingebunden habe.
Zitat
Nur wenn du das brauchst, macht es Sinn, keine harten Referenzen zu haben und die Assemblies feinkörnig aufzuteilen.

Meistens braucht es dies nicht und die Nachteile, die diese Vorgehensweise mit sich zieht, sind grösser als die Vorteile.

Wieso gibt es da so viele Nachteile ? So wie ich das sehe , verdrahte ich in meiner jeweiligen Klasse ja nur 2 Assemblys : Das Model als Assembly und das Interface des generischen Repositorys, wessen konkrete Implementierung ich über den DI Container auflöse.
Das wäre eigtl. gängiger Standard um absolut Austauschbar zu bleiben oder irre ich mich da ?

Grüße
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Ahrimaan am .
private Nachricht | Beiträge des Benutzers
Peter Bucher
myCSharp.de - Experte

Avatar #jVxXe7MDBPAimxdX3em3.jpg


Dabei seit:
Beiträge: 6141
Herkunft: Zentralschweiz

beantworten | zitieren | melden

Hallo Ahrimaan
Zitat von Ahrimaan
Das verstehe ich aber nicht so recht : Wenn ich eh eine Konkrete Implementierung in eine Assembly packe, muss ich ja nicht mehr zwingend gegen das interface schreiben, sondern kann direkt auf die Implementation zugreifen, da ich die Assembly ja eh eingebunden habe.
Das ist genau der Punkt.

Gegen ein Interface implementieren "reicht", könnte man sagen.

Ob du auf die Implementation eine harte Referenz hast / oder diese im gleichen Assembly hast (ist hierfür beides dasselbe), resultiert einzig und alleine nur im Unterschied, dass du die ganze Anwendung neu kompilieren musst, um deine Anwendung auf einer andere Implementation umzubiegen. Das ist aber alles.

So wie du schreibst, beziehst du den zweiten Teil - der nicht so relevant ist - als _der_ Grund für DI, bzw. dass es ohne diesen keine Rolle spielt.

Genau das ist eben nicht so.

Ausser du meinst mit "nicht mehr zwingend" die Gefahr, das du aus Versehen irgendwo den konkreten Typen benutzt, weil du ihn benutzen kannst.
Zitat von Ahrimaan
Wieso gibt es da so viele Nachteile ? So wie ich das sehe , verdrahte ich in meiner jeweiligen Klasse ja nur 2 Assemblys : Das Model als Assembly und das Interface des generischen Repositorys.
Das wäre eigtl. gängiger Standard um absolut Austauschbar zu bleiben oder irre ich mich da ?
Ich muss mich korrigieren: "Man handelt sich damit einige Nachteile ein, die nicht sein müssten, wenn man den einen Vorteil nicht braucht".

Als Beispiel kannst du in deiner Anwendung die DI-Registrierung nicht per Code machen (Delegates), auch die NHibernation müsstest du per Xml machen.

Das ist ein wesentlicher Nachteil, da die Typsicherheit und der Komfort der Registrierung nachlässt.


Gruss Peter
--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

- https://peterbucher.ch/ - Meine persönliche Seite
- https://fpvspots.net/ - Spots für FPV Dronenflüge
private Nachricht | Beiträge des Benutzers
Ahrimaan
myCSharp.de - Member



Dabei seit:
Beiträge: 363
Herkunft: Thorn

Themenstarter:

beantworten | zitieren | melden

Hallo Peter,
Zitat
Ausser du meinst mit "nicht mehr zwingend" die Gefahr, das du aus Versehen irgendwo den konkreten Typen benutzt, weil du ihn benutzen kannst.

Genau das meine ich :-)
Zitat
Als Beispiel kannst du in deiner Anwendung die DI-Registrierung nicht per Code machen (Delegates), auch die NHibernation müsstest du per Xml machen.

Das ist ein wesentlicher Nachteil, da die Typsicherheit und der Komfort der Registrierung nachlässt.

Stimmt das wäre in dem Sinne unkomfortabel. Ich habe aber bewusst diese Art der implementierung gewählt, da ich mit FluentNhibernate ohne "Harte" Koppelung bei Änderungen nur die dll des Repositorys nachschiebe.

Grüße
private Nachricht | Beiträge des Benutzers
temilun
myCSharp.de - Member



Dabei seit:
Beiträge: 6

beantworten | zitieren | melden

Keine Ahnung ob das gut ist, aber ich mach das so:

-Project.Module1
-Project.Module2
-Project...
-Project.Shared
-Project.Dal

In Shared sind die Interfaces, Entities usw. auf die alle den Zugriff brauchen und die von allen referenziert wird. Der Rest läuft über DI.
private Nachricht | Beiträge des Benutzers
gfoidl
myCSharp.de - Team

Avatar #avatar-2894.jpg


Dabei seit:
Beiträge: 7561
Herkunft: Waidring

beantworten | zitieren | melden

Hallo temilun,

die Entities würde ich nicht in Shared haben (wollen). In Shared können, wie du es auch hast, die Interfaces liegen und sonstige geteilte Funktionalitäten wie Erweiterungsmethoden, Logging-Komponente, etc.

Die Entities, wenn sie POCOs sind, gehören in einen eigenen Model-Namespace (und ev. auch in ein eigenes Projekt).

Somit ergibt sich grob solche Struktur (der Solution):

MySuperApplication
- MySuperApplication.Shared (od. z.B. auch als Common bezeichnet)
- MySuperApplication.DataAccess
- MySuperApplication.Services
- MySuperApplication.Models
- MySuperApplication.ViewModels
- MySuperApplication.View
- MySuperApplication (die EXE, die nicht viel mehr macht als alles (per DI) zu laden und verbinden)
auf die Test-Projekte hab ich hier verzichtet, die gehören aber auch dazu. Angehängt ein Bild das die Schichten zeigt, die ähnlich obiger Projektstruktur sind ,nur die Bezeichnungen sind tw. anders. Das Bild hab zwar ich generiert, aber der Code stammt von einem MS ALM-Ranger-Demo-Projekt. Die Pfeile zeigen die Abhängigkeiten zwischen den einzelnen Projekten.

Aber: die Strukturierung eines Projekts ist z.T. auch Geschmackssache und bietet somit viel Raum für Diskussionen. Von daher bitte das in diesem Thread nicht zu intensiv behandeln.

mfG Gü
Attachments
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
private Nachricht | Beiträge des Benutzers