W jaki sposób działa inicjalizowanie kontekstu bazy danych przez konstruktor?

0

Witam serdecznie, na wstępie tylko dodam, że w c# stawiam swoje pierwsze kroki, dlatego jeśli w niektórych momentach pomylę jakieś pojęcia bardzo proszę o wyrozumiałość.

Stworzyłem już kilka prostych projektów aplikacji webowych i zawsze ciekawiła mnie jedna rzecz, a dokładnie tworzenie instancji kontakstu bazy danych. Otóż powiedzmy, że mamy taki standardowy kontroler:

public class QuestionsController
{
  private readonly QuizContext _context;

  public QuestionsController(QuizContext context)
  {
    _context = context;
  }
}

W tym momencie zainicjalizowałem w kontrolerze zmienną _context więc mogę użyć jej aby uzyskać dostęp do bazy danych:

public ActionResult GetQuestions()
{
return _context.Questions.ToList();
}

I oczywiście wszystko działa poprawnie. W momencie gdy otworzę klasę QuizContext znajduje się tam konstruktor, który przyjmuje jako parametr DbContextOptions<QuizAppContext> options:

public class QuizContext : DbContext
{
        public QuizContext(DbContextOptions<QuizAppContext> options) : base(options)
        {
            
        }
}

Totalnie nie mogę zrozumieć, w jaki sposób w ww. kontrolerze udało mnie się stworzyć nową instancję klasy QuizContext bez podawania w którymś momencie obiektu tego konstruktora. Przecież w momencie, gdyby stworzył instancję QuizContext w taki sposób:

public class QuestionsController
{
  private readonly QuizContext _context =  new QuizContext (new DbContextOptions<QuizContext >());
}

Muszę go podać. W przypadku inicjalizowania QuizContext za pomocą kontruktora, w jaki sposób program tworzy nową instancję tego obiektu, skoro nigdzie nie muszę podawać parametru konstruktora klasy QuizContext?

5

Tak to jest jak się zaczyna programowanie od d**y strony, czyli bierzemy czyjś kod i zastanawiamy dlaczego on działa. Według mnie to jest średnia ścieżka.

Zastanawiałeś się kto tworzy instancję tego kontrolera? Tworzony jest w fabryce kontrolerów ukrytej wewnątrz frameworka, która korzysta z wbudowanego (bądź nie) kontenera IoC do zbudowania drzewa obiektów. A twój DbContext jest tam zarejestrowany, bo zapewne sam go dodałeś w Startup jakimś AddDbContext.

Do poczytania hasła: IoC, dependency inversion, composition root.

7

Mechanizm/Technika zwana jako Dependency Injection potrafi poukładać sobie zależności aby być w stanie utworzyć dany obiekt, a jak nie, to będzie krzyczał przy próbie stworzenia.

W twoim przypadku pewnie podczas podpinania bazki w Startupie od razu konfiguruje ci się DI i podpina te wszystkie klasy, oraz też jest ileś tam defaultowo wpiętych (tak mi się wydaje)

Dependency injection in ASP.NET Core

Piekielnie istotną kwestią jest tutaj Lifetime.

@Saalin:

używasz rzeczy, których nie rozumiesz zamiast zacząć od podstaw. Traktujesz framework jako magię. Nie ma znaczenia czy kod jest z tutoriala, czy ukradziony czy wygenerowany.

czyli sugerujesz że miał klepać console appki aż tam nie napotka DI?

przecież hello world w ASP już od startu mocno wykorzystuje DI i inne mechanizmy, patterny itd.

2

No niestety, nowoczesne IDE i frameworki pozwalają szybko wystartować, ale ukrywają tak wiele istotnych elementów, że to się często szybko kończy katastrofą.

WeiXiao napisał(a):

czyli sugerujesz że miał klepać console appki aż tam nie napotka DI?

Owszem, a potem napisać swój kontener - żeby czasem nie myśleć, że w jego wnętrzu jakaś magia się dzieje.
Oczywiście można iść na skróty, pytanie, czy to zawsze najlepsze rozwiązanie.

przecież hello world w ASP już od startu mocno wykorzystuje DI i inne mechanizmy, patterny itd.

Dlatego właśnie warto je znać i rozumieć, żeby wiedzieć gdzie szukać błędów, albo gdzie trzeba coś dopisać.

3
WeiXiao napisał(a):

@Saalin:

używasz rzeczy, których nie rozumiesz zamiast zacząć od podstaw. Traktujesz framework jako magię. Nie ma znaczenia czy kod jest z tutoriala, czy ukradziony czy wygenerowany.

czyli sugerujesz że miał klepać console appki aż tam nie napotka DI?

przecież hello world w ASP już od startu mocno wykorzystuje DI i inne mechanizmy, patterny itd.

Sugeruję nie ruszanie ASP przed poznaniem standardowych patternów. My tu mówimy naprawdę o czymś zupełnie podstawowym, przecież mowa o SOLID. Każdy kto miał wcześniej styczność z DI od razu zobaczy, że w tym wątku wcale nie chodzi o inicjalizowanie kontekstu bazy danych, tylko o constructor injection, które będzie tak samo działać dla dowolnej wstrzykniętej zależności.

Mój zarzut jest taki: OP sam pisze, że stawia pierwsze kroki w C#, a już ma aplikację z DI i bazą danych i próbuje uczyć się top-down, a ja sugeruję bottom-up właśnie od konsolowych aplikacji. Chyba, że uważasz, że w konsolowych aplikacjach nie ma miejsca na odwrócenie zależności, bo wg mnie można nawet więcej z tego wyciągnąć, np. doświadczyć DI bez kontenera IoC.

0

Mój zarzut jest taki: OP sam pisze, że stawia pierwsze kroki w C#, a już ma aplikację z DI i bazą danych i próbuje uczyć się top-down, a ja sugeruję bottom-up właśnie od konsolowych aplikacji.

A właściwie czemu?

Klepiąc sobie konsol appki możesz nawet nie mieć świadomości że takie mechanizmy istnieją, a tutaj nie pójdziesz dalej bez nich i wymuszą abyś się ich nauczył chociaż na tyle, aby móc ich używać.

Uważam również, że idąc od góry do dołu łatwiej o zabawę, bo łatwiej coś sensowniejszego napisać, co przy okazji można było gdzieś wystawić na świat

A przy pure console appkach* wydaje mi się że trzeba umieć dużo więcej, aby napisać coś sensownego bo zazwyczaj są to jakieś narzędzia - git, docker, kompilator, baza danych, itp.

* to takie uproszczenie, bo przecież web appka to tez console appka.

1 użytkowników online, w tym zalogowanych: 0, gości: 1