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