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 » Grundlagen von C# » Dependency Injected DbContext in Statischer Klasse für Hilfsmethoden nutzen legitim?
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Dependency Injected DbContext in Statischer Klasse für Hilfsmethoden nutzen legitim?

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

Dabei seit: 19.04.2018
Beiträge: 30


monsee ist offline

Dependency Injected DbContext in Statischer Klasse für Hilfsmethoden nutzen legitim?

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

Morgen zusammen,

ist es eigentlich legitim und praxisnah, von einem Controller bzw. einer PageModel Klasse die injizierte DbContext in eine statische Methode einer statischen Klasse als Parameter mitzugeben?

Also z.B.: public static async Task<Auto> GetAutoById(int id, ApplicationDbContext _context)
...

Zweck ist, dass ich eine Datenbankabfrage mehrfach verwenden will, es aber aus meiner Sicht keinen Sinn macht jedes mal eine Instanz meiner Helper-Method zu machen und erst recht nicht die Methode jedesmal im jeweiligen PageModel neuzuschreiben, weswegen ich die alle statisch halte.

In meiner PageModel-Klasse sorgt dies sichtbar für mehr Überblick.

Noch ein Hinweis, das sind nur Hilfsmethoden. Die CRUD-Operations werden natürlich in den jeweiligen PageModels durchgeführt.

Oder baue ich mir damit Hürden auf?

monsee

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von monsee am 10.08.2018 10:03.

10.08.2018 10:01 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.174
Herkunft: Stuttgart/Stockholm


Abt ist offline

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

Eine statische Klasse ist so nicht testbar, geschweige denn die Methode.
Dadurch nein, so absolut nicht legitim.
10.08.2018 10:41 Beiträge des Benutzers | zu Buddylist hinzufügen
monsee monsee ist männlich
myCSharp.de-Mitglied

Dabei seit: 19.04.2018
Beiträge: 30

Themenstarter Thema begonnen von monsee

monsee ist offline

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

Hallo Abt,

also die statische Klasse dann in eine nicht statische umwandeln und die DbContext via DI injizieren und dann Instanzen in der PageModel Klasse davon nutzen oder wie macht man das sauber?

Gruß, monsee
10.08.2018 10:43 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Taipi88 Taipi88 ist männlich
myCSharp.de-Mitglied

avatar-3220.jpg


Dabei seit: 02.02.2010
Beiträge: 979
Entwicklungsumgebung: VS 2010
Herkunft: Mainz


Taipi88 ist offline

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

Hi,

ich denke eher, dass der Ansatz für eine derart simple Methode (wenn man dem Namen der Methode glauben darf) eine Hilfsklasse zu benötigen schon quer liegt.

Ich muss zugeben, dass ich nur sehr selten EF verwende und wenn dann auch nur für Quick&Dirty-Aufgaben - in wichtigeren Anwendungen verwende ich Dapper in Verbindung mit dem RepositoryPattern (wobei ich nicht sicher bin ob dieses für EF so intelligent ist, da EF selbst ja schon was ähnliches bietet) - das Thema ist - du willst offensichtlich eine Entity per Id aus der DB holen - eine Standardaufgabe für ein Repository, womit diese Funktion eben in's Repository - und nicht in eine Hilfsklasse gehört.

Wenn ich dort an EF denke - sind DbSets das, was einem Repository am nächsten kommt - und mir fällt adhoc ehrlich gesagt kein Grund ein vll ein eigenes bzw. abgeleitetes DbSet zu verwenden, dass genau eine solche Methode bereitstellt.

LG

PS: Abseits davon überhaupt eine solche Hilfsklasse zu brauchen - halte ich es für ziemlich ungeschickt eine solche auch noch static zu haben - wenn du das für mehr als ein Model machst - hast du ruckzuck soviele Helper wie Entitäten - alle statisch und nicht zu testen...

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Taipi88 am 10.08.2018 10:55.

10.08.2018 10:54 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.174
Herkunft: Stuttgart/Stockholm


Abt ist offline

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

C#-Code:
public static async Task<Auto> GetAutoById(int id, ApplicationDbContext _context)

1) die Methode sollte an dieser Stelle GetAutoByIdAsync heissen, um Konform mit dem Framework zu sein
2) diese Klasse ist ein typischer Fall für den Repository Pattern, wobei der DbContext den UnitOfWork darstellt

Sehe keine Notwendigkeit einer Hilfsklasse.
10.08.2018 10:54 Beiträge des Benutzers | zu Buddylist hinzufügen
Palladin007 Palladin007 ist männlich
myCSharp.de-Mitglied

Dabei seit: 03.02.2012
Beiträge: 1.205
Entwicklungsumgebung: Visual Studio 2017
Herkunft: NRW


Palladin007 ist offline

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

Ohne der abschließenden Aussage bezüglich dem Repository widersprechen zu wollen:

Zitat:
Eine statische Klasse ist so nicht testbar, geschweige denn die Methode.

Für mich sieht die Methode so aus, als bräuchte sie keinen Zustand. Damit ist sie durchaus testbar, solange man ApplicationDbContext mocken kann.


Wenn ich unbedingt eine Quick&Dirty-Lösung schreiben will, dann würde ich das aber als Extension-Method für die DbSets bauen. Ist im Prinzip nichts anderes als eine statische Methode, nur die Nutzung sieht wie ein Instanz-Zugriff aus. Und weil das so ist, kann man das leichter durch eine saubere Repository-Lösung ersetzen, da die Aufrufe sich nicht ändern würden - zumindest solange die Signatur gleich bleibt.

Bei EF ist diese konkrete Methode aber gar nicht notwendig, denn EF bietet dafür die Find-Methode an. Bei EF6 nur am DbSet, bei EFCore findet man die sowohl am DbContext als auch am DbSet.
10.08.2018 11:21 Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


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


Abt ist offline

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

Zitat von Palladin007:
Damit ist sie durchaus testbar, solange man ApplicationDbContext mocken kann.

Naja, aber Du kennst ja den DbContext von EF - der ist so nicht mockbar; nur über Shims.
10.08.2018 11:27 Beiträge des Benutzers | zu Buddylist hinzufügen
monsee monsee ist männlich
myCSharp.de-Mitglied

Dabei seit: 19.04.2018
Beiträge: 30

Themenstarter Thema begonnen von monsee

monsee ist offline

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

geschockt

Bitte helft mir als Hobbyprogrammierer, der sich grade das Repository Pattern einverleibt.
Was ist denn jetzt Mock schon wieder?

monsee
10.08.2018 11:33 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.174
Herkunft: Stuttgart/Stockholm


Abt ist offline

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

10.08.2018 11:42 Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.390
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist online

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

s.  Mock-Objekt

@Abt: Aber auch eine nicht-statische Methode wäre dann nicht testbar bzw. mock-fähig (solange der DbContext übergeben bzw. benutzt wird).
Es hat mit der Testbarkeit nichts zu tun, ob eine Klasse oder Methode selber statisch ist oder nicht - es kommt drauf an, ob die Methode intern andere Methoden aufruft, welche nicht austauschbar sind.
Wenn also eine nicht-statische Methode z.B. Console.WriteLine oder Math.Sin oder eine andere statische Methode aufruft, dann läßt sich diese nicht mocken. Aber dasselbe gilt genauso für Aufrufe innerhalb von nicht-statischen Methoden, solange man Objekte von konkreten Klassen (und Strukturen) benutzt! Erst bei der konsequenten Benutzung von Schnittstellen (interface), d.h. üblicherweise per DI übergeben, lassen sich Methoden soweit mocken, daß sie unabhängig von externen Klassen sind.

Beispiel:

C#-Code:
interface IX
{
  int Value { get };
}

static int Add(IX x, IX y)
{
  return x.Value + y.Value;
}

Diese Methode ist nun test- und mock-bar, egal ob static oder nicht.

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Th69 am 10.08.2018 11:51.

10.08.2018 11:46 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.174
Herkunft: Stuttgart/Stockholm


Abt ist offline

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

Deswegen gibt es nicht nur Mock-Objekte, sondern auch Shim-Objekte.

Gut, wenn Du es jetzt auf static beziehst; ich hab meine Aussage dahingehend auch vereinfacht ausgedrückt.
Es macht ja keinen Sinn in diesem Kontext nun auf die Feinheiten einzugehen.

Statische Methoden (im überwiegenden Teil) sind nicht testbar, weil nicht austauschbar.
Dass dies natürlich für gewisse Pattern nicht gilt; macht jetzt den Braten nicht fett.
10.08.2018 11:51 Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.390
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist online

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

Aber nur einfach zu schreiben (ist ja nicht das erste mal von dir):

Zitat von Abt:
Eine statische Klasse ist so nicht testbar, geschweige denn die Methode.

finde ich nicht sehr hilfreich (für die Leser).
Einfach nur das static zu löschen, reicht eben nicht aus.

Leider gibt es keine Möglichkeit (kenne ich aber auch von anderen Programmiersprachen nicht), eine Methode so zu deklarieren, daß sie keine anderen (statischen) Methoden aufruft (z.B. strict).

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am 10.08.2018 12:01.

10.08.2018 12:00 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.174
Herkunft: Stuttgart/Stockholm


Abt ist offline

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

Nehme ich an, dass Du dies in dieser Form kritisierst.
Ist immer ein schmaler Grat zwischen "zu viel schreiben, was die Leute oft direkt erschlägt" und eben prägnant auf den Punkt zu kommen, und dadurch evtl. pauschal zu wirken.

Ich habe jedoch nicht geschrieben, dass eine statische Klasse/Methode pauschal nicht testbar sei.
Ich habe geschrieben, dass sie *so* nicht testbar sei. Das ist inhaltlich ein deutlicher Unterschied.
Schreibe schließlich auch nirgends, dass static löschen reichen würde.
Dahingehend kann ich die Kritik auch so nur teilweise nachvollziehen.
10.08.2018 12:13 Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.390
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist online

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

Aber das testbar hat eben nichts mit "static" zu tun, und genau so klingt aber deine Aussage.
Ich schreibe ja z.B. auch nicht, daß async oder void nicht testbar ist...

Mir ging's nur darum, klarzustellen, daß statische Methoden nicht die "Wurzel allen Übels" sind.
So empfiehlt ja auch die Code Analysis (früher FXCop)  CA1822: Mark members as static.

PS: Und selbst in  [Artikel] Unit-Tests: Einführung in das Unit-Testing mit VisualStudio wird als Beispiel eine statische Methode getestet.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am 10.08.2018 13:09.

10.08.2018 13:05 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.174
Herkunft: Stuttgart/Stockholm


Abt ist offline

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

Tut mir leid, aber ich will Dein Goldwaagen-Spiel nicht wirklich mitmachen.

Denn...nun klingt Deine Aussage

Zitat von Th69:
So empfiehlt ja auch die Code Analysis (früher FXCop)  CA1822: Mark members as static.

alleinstehend, als ob man alles static deklarieren soll.
Ne, sorry - Goldwaagenspiele sind nicht meins.

Ich stehe aber weiterhin zu meiner Aussage, es ist potentiell schlimmer static unbewusst zuviel zu verwenden als umgekehrt.
10.08.2018 14:23 Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.390
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist online

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

Wer legt jetzt was auf die Goldwaage?
Lies doch den Link.

OK, ich zitiere den m.E. wichtigen Satz:

Zitat:
Cause

A member that does not access instance data is not marked as static.

Und gerade Hilfsmethoden (die nur auf den übergebenden Parametern beruhen), erfüllen dies (und sind genauso testbar oder untestbar wie nicht-statische Methoden auch).

Aber da du anscheinend es nicht einsehen willst, werde ich wohl weiter in diesem Forum von dir den (oder ähnlichen) Satz lesen (müssen):

Zitat von Abt:
Statische Klassen oder Methoden sind (so) nicht testbar.
10.08.2018 14:40 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.174
Herkunft: Stuttgart/Stockholm


Abt ist offline

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

Richtig, sofern es auf die jeweilige Klasse zutrifft, werde ich das weiterhin so formulieren. Denn

Zitat von Abt:
Ich stehe aber weiterhin zu meiner Aussage, es ist potentiell schlimmer static unbewusst zuviel zu verwenden als umgekehrt.

Dass C# darüber hinaus über Sprachfeatures verfügt, die static sein müssen und dabei trotzdem testbar sind - sofern korrekt umgesetzt - ist sogar mir bewusst.
10.08.2018 15:01 Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 5 Monate.
monsee monsee ist männlich
myCSharp.de-Mitglied

Dabei seit: 19.04.2018
Beiträge: 30

Themenstarter Thema begonnen von monsee

monsee ist offline

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

Guten Morgen zusammen,

ich krame mal meinen alten Thread heraus, in dem es um den möglichen Einsatz des UnitOfWork-Pattern geht.

Ich habe mir einige Lernvideos dazu angesehen und in mein Projekt das Pattern eingebunden.

Die Videos, die ich mir angesehen habe, zeigen aber alle auf, wie ich mit der UoW Daten aus der Datenbank abhole. Während die CUD-Methoden dann zum Beispiel in einem ASP.NET-Projekt in den jeweiligen Controller (MVC) bzw. EventHandler-Methoden (Razor Pages) über die Unit Of Work durchgeführt werden.

Verfehlt das nicht irgendwie denn Sinn?

Wenn ich einen Datensatz erstellen will, dann könnte ich die Methode dafür doch auch im Repository der UoW unterbringen und in der EH-Methode dann sowas wie
_unitOfWork.Autos.CreateAuto(auto) aufrufen, anstatt den ganzen Salmon in die Code-Behind zu schreiben - oder?

Gruß, monsee
18.01.2019 09:49 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.174
Herkunft: Stuttgart/Stockholm


Abt ist offline

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

Kannst Du bitte die Quelle verlinken, auf die Du Dich beziehst oder wenigstens den Code dazu zeigen?
Noch nicht jeder von uns kann hellsehen ;-)
18.01.2019 16:57 Beiträge des Benutzers | zu Buddylist hinzufügen
monsee monsee ist männlich
myCSharp.de-Mitglied

Dabei seit: 19.04.2018
Beiträge: 30

Themenstarter Thema begonnen von monsee

monsee ist offline

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

Oh, hallo ABT, dass wird etwas Schwierig mit dem Link.
Das ist ein Udemy-Kurs.

Da geht es um die Einführung ins EF-Framework.

Der Autor zeigt da zwar die vollständige Einrichtung, aber geht überwiegend nur auf die Abfrage von Daten ein, nicht aber, ob die UoW auch logischerweise die Methoden für CUD enthalten sollten.

Gruß, monsee
18.01.2019 21:07 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.174
Herkunft: Stuttgart/Stockholm


Abt ist offline

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

In EF ist der DbContext bereits der UoW Context.
Und das Repository bekommt den DbContext injiziert.

C#-Code:
.. class UserRepository : BaseRepository, IUserRepository...


public async Task<UserEntity> AddAsync(string userName)
{
.....

   UserEntity user ...
   await _dbContext.Users.AddAsync(user);

   return user;
}

Es gibt manchmal Situationen, da lohnt es sich den DbContext erneut zu abstrahieren - aber nicht immer.

Der DbContext - egal wie - gehört aber weder in die Action, noch in Razor Pages.
Das wird gern in einfachen Samples gemacht - ist aber eine starke Verletzung der  [Artikel] Drei-Schichten-Architektur

Razor Pages und Controller/Action gelten als UI-Schicht.
Weder DbContext noch Repositories haben daher irgendwas in Razor Pages oder Actions zu suchen.
Da hat nur die Business Logik zu sein, die aufgerufen wird.

Ein Beispiel dazu siehst Du in einem GitHub Repository von mir, das ich für Talks in UserGroups und Konferenzen verwende/verwendet hab:
 https://github.com/BenjaminAbt/2018-Talk...nApiDevelopment

Controller kennen hier nur die Business Schicht (hier Event-driven via MediatR) und in der Business Schicht (hier eben EventHandler) wird dann auf ein Repository zugegriffen.
Nur so kann Business Logik über Anwendungen/Projekte hinweg geteilt werden. Das klappt nicht, wenn man Business Logik Plain in die UI schubst - da gehört sie nicht hin.
18.01.2019 21:50 Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als ein Jahr.
Der letzte Beitrag ist älter als 9 Monate.
Antwort erstellen


© Copyright 2003-2019 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 15.11.2019 15:44