Blog

ASP.NET Core: wiele kontekstów i baz danych

Jak rozdzielić model na wiele DbContext i baz w ASP.NET Core z EF Core i Identity: konfiguracja, migracje, DI, przykład użycia i dobre praktyki skalowania oraz porządkowania logów.

Mateusz Kopta

Wprowadzenie

Pierwsza wersja aplikacji zwykle powstaje gładko: mamy dokumentację, konfigurujemy środowiska, wdrażamy i… rosnący wykres użytkowników cieszy. Do czasu, gdy baza danych puchnie wykładniczo i spowalnia całą platformę.

Źródło problemu? Jedna, monolityczna baza gromadzi zarówno dane domenowe, jak i logi operacyjne. Rozwiązanie: rozdzielić odpowiedzialności na wiele kontekstów i baz danych, zachowując spójny model w kodzie.

Cel i założenia

- Podzielić dane na mniejsze, niezależne zbiory - Mieć prosty sposób obsługi wielu DbContext z poziomu aplikacji - Utrzymać prosty proces migracji w EF Core

Stos technologiczny

ASP.NET Core 2.x, Entity Framework Core (Code First) oraz Identity.

Model przykładowej aplikacji

Załóżmy proste forum. Użytkownicy tworzą wątki, wewnątrz których znajdują się posty. Dodatkowo rejestrujemy aktywności użytkowników jako logi.

- Dane domenowe: Users, Threads, Posts - Logi: UserActionLog

Dwa konteksty, dwie bazy

Pierwszy kontekst obsługuje dane domenowe i dziedziczy po IdentityDbContext, dzięki czemu łączy użytkowników z Thread i Post. Drugi kontekst, oparty o DbContext, przechowuje wyłącznie wpisy logów użytkowników.

- DomainDbContext: Identity + Threads + Posts - ActionLogDbContext: UserActionLogs

Korzyści:

- Wyraźne granice odpowiedzialności i prostsze utrzymanie - Niezależne cykle życia i strategie retencji danych - Możliwość skalowania i osobnego strojenia każdej bazy

Fabryki i agregator kontekstów

Aby wygodnie pozyskiwać właściwy DbContext, definiujemy interfejs fabryki oraz implementacje dla każdego kontekstu. Rejestrujemy je w DI ASP.NET Core. Na koniec tworzymy lekki agregator, który pakuje fabryki i zwraca żądany kontekst po kluczu lub typie.

- IDbContextFactory: kontrakt do tworzenia DbContext - ActionLogDbContextFactory i DomainDbContextFactory: implementacje rejestrowane w DI - DbContexts: obiekt agregujący, udostępniający konteksty przez indeksator

Dzięki temu w dowolnym miejscu aplikacji pobieramy właściwe źródło danych bez duplikacji konfiguracji.

Rejestracja w Startup

W ConfigureServices rejestrujemy oba konteksty z oddzielnymi connection stringami z appsettings.json, a także fabryki i agregator DbContexts. Web host korzysta z klasy Startup podczas uruchamiania aplikacji.

- Przykładowe nazwy connection stringów: DomainDataDbConnection oraz ActionLogDataDbConnection

Migracje dla wielu kontekstów

EF Core obsługuje wiele kontekstów w migracjach przy użyciu parametru -Context oraz własnych katalogów migracji. Uruchamiamy dwie serie poleceń Add-Migration i Update-Database, po jednej na każdy kontekst, wskazując także projekt startowy przez -Startup.

Przykładowe polecenia Add-Migration:

Add-Migration Initial -Context DomainDbContext -OutputDir Migrations/DomainDbContextMigrations -Startup MultipleContextsApp.Web

Add-Migration Initial -Context ActionLogDbContext -OutputDir Migrations/ActionLogDbContextMigrations -Startup MultipleContextsApp.Web

Następnie aktualizacja baz:

Update-Database -Context DomainDbContext -Startup MultipleContextsApp.Web

Update-Database -Context ActionLogDbContext -Startup MultipleContextsApp.Web

W efekcie otrzymujemy dwie niezależne historie migracji i przejrzystą strukturę w warstwie modelu.

Użycie w aplikacji

DbContexts (agregator) wstrzykujemy tam, gdzie potrzebujemy dostępu do danych: w kontrolerach, handlerach czy – lepiej – w warstwie dostępu do danych (DAL). DAL wystawia następnie interfejs dla wyższych warstw.

Przykład zastosowania w kontrolerze:

- Metoda GetActions pobiera wpisy z ActionLogDbContext, korzystając z połączenia ActionLogDataDbConnection - Metoda GetThreads pobiera wątki z DomainDbContext, korzystając z DomainDataDbConnection

Dobre praktyki

- Rozdzielaj dane o różnej dynamice i retencji (np. logi vs. dane biznesowe) - Każdemu kontekstowi zapewnij własny katalog migracji - Monitoruj połączenia i limity, skalując bazy niezależnie - Ukrywaj szczegóły dostępu do danych za DAL, aby zachować modułowość

Podsumowanie

Zbudowaliśmy szkielet aplikacji webowej korzystającej z wielu DbContext i baz danych. Mamy klarowny podział odpowiedzialności, prostsze migracje i elastyczność skalowania. W większych projektach wstrzykujemy agregator kontekstów do DAL, co upraszcza utrzymanie i rozwój.

Masz pytania lub chcesz ocenić, czy Twoja baza wytrzyma wzrost ruchu? Skontaktuj się z nami – przygotujemy bezpłatną analizę.

Potrzebujesz wsparcia technologicznego?

Porozmawiajmy o Twoim projekcie — od discovery po wdrożenie.

Umów konsultację

Chcesz wiedzieć więcej?

Sprawdź inne artykuły lub porozmawiajmy o Twoim projekcie

Wszystkie artykuły Zaprojektujmy Twoją aplikację AI
An unhandled error has occurred. Reload 🗙