Entity Framework: jedna baza danych, wiele DbContexts. Czy to zły pomysł? [Zamknięte]

213

Do tej pory DbContextmam wrażenie, że a ma reprezentować twoją bazę danych, a zatem, jeśli twoja aplikacja korzysta z jednej bazy danych, potrzebujesz tylko jednej DbContext.

Jednak niektórzy koledzy chcą podzielić obszary funkcjonalne na osobne DbContextklasy.

Wierzę, że pochodzi to z dobrego miejsca - z chęci utrzymania kodu w czystości - ale wydaje się niestabilne. Mój żołądek mówi mi, że to zły pomysł, ale niestety moje przeczucie nie jest wystarczającym warunkiem do podjęcia decyzji projektowej.

Więc szukam:

A) konkretne przykłady, dlaczego może to być zły pomysł;

B) zapewnienia, że ​​wszystko się uda.

Josh Schultz
źródło
Zobacz moją odpowiedź: stackoverflow.com/questions/8244405/…
Mohsen Alikhani,

Odpowiedzi:

168

Możesz mieć wiele kontekstów dla pojedynczej bazy danych. Może to być przydatne na przykład, jeśli baza danych zawiera wiele schematów bazy danych i chcesz obsłużyć każdy z nich jako osobny, niezależny obszar.

Problem polega na tym, że najpierw chcesz użyć kodu do utworzenia bazy danych - może to zrobić tylko jeden kontekst w aplikacji. Sztuką tego jest zazwyczaj jeden dodatkowy kontekst zawierający wszystkie twoje jednostki, który jest używany tylko do tworzenia bazy danych. Rzeczywiste konteksty aplikacji zawierające tylko podzbiory twoich jednostek muszą mieć inicjator bazy danych ustawiony na null.

Istnieją inne problemy, które zobaczysz podczas korzystania z wielu typów kontekstu - na przykład typy jednostek współdzielonych i ich przekazywanie z jednego kontekstu do drugiego itp. Zasadniczo jest to możliwe, może uczynić twój projekt znacznie czystszym i oddzielić różne obszary funkcjonalne, ale ma swoje dodatkowe koszty.

Ladislav Mrnka
źródło
21
Używanie jednego kontekstu na aplikację może być kosztowne, jeśli aplikacja ma wiele jednostek / tabel. Dlatego w zależności od schematu sensowne może być także posiadanie wielu kontekstów.
DarthVader
7
Ponieważ nie subskrybuję pluralsight, znalazłem ten niesamowity artykuł Julie Lerman ( jej komentarz ) napisany dobrze po tym pytaniu , ale bardzo odpowiedni: msdn.microsoft.com/en-us/magazine/jj883952.aspx
Dave T.
Sugeruję strukturę encji do obsługi wielu kontekstów db db w tej samej bazie danych przez konwencję nazewnictwa. Z tego powodu wciąż piszę własną ORM do modułowej aplikacji. Trudno w to uwierzyć, co zmusza jedną aplikację do korzystania z jednej bazy danych. Zwłaszcza w gospodarstwach internetowych masz ograniczoną liczbę baz danych
wolną wolę
Dodatkowo zdałem sobie sprawę, że możesz włączyć migracje tylko dla jednego kontekstu w projekcie za pośrednictwem PM Console.
Piotr Kwiatek
9
@PiotrKwiatek Nie jestem pewien, czy zmieniło się to między Twoim komentarzem a teraz, ale Enable-Migrations -ContextTypeName MyContext -MigrationsDirectory Migrations\MyContextMigrationsdziała teraz.
Zack,
60

Napisałem tę odpowiedź około cztery lata temu i moje zdanie się nie zmieniło. Ale od tego czasu nastąpił znaczny rozwój w dziedzinie mikrousług. Na końcu dodałem uwagi dotyczące mikrousług ...

Zastanowię się nad tym pomysłem, mając doświadczenie w świecie rzeczywistym, aby poprzeć mój głos.

Zostałem przeniesiony do dużej aplikacji, która miała pięć kontekstów dla jednej bazy danych. Ostatecznie usunęliśmy wszystkie konteksty oprócz jednego - wracając do jednego kontekstu.

Na początku pomysł wielu kontekstów wydaje się dobrym pomysłem. Możemy podzielić dostęp do danych na domeny i zapewnić kilka czystych, lekkich kontekstów. Brzmi jak DDD, prawda? Uprościłoby to nasz dostęp do danych. Kolejny argument przemawia za wydajnością, ponieważ uzyskujemy dostęp tylko do potrzebnego kontekstu.

Ale w praktyce, wraz z rozwojem naszej aplikacji, wiele naszych tabel łączyło relacje w różnych kontekstach. Na przykład zapytania do tabeli A w kontekście 1 wymagały również dołączenia do tabeli B w kontekście 2.

Pozostało nam kilka kiepskich wyborów. Możemy powielić tabele w różnych kontekstach. Próbowaliśmy tego. Stworzyło to kilka problemów z mapowaniem, w tym ograniczenie EF, które wymaga, aby każda jednostka miała unikalną nazwę. Skończyło się na tym, że w różnych kontekstach istniały byty Person1 i Person2. Można argumentować, że był to zły projekt z naszej strony, ale pomimo naszych najlepszych starań, tak właśnie nasza aplikacja wzrosła w prawdziwym świecie.

Próbowaliśmy także zapytać w obu kontekstach, aby uzyskać potrzebne dane. Na przykład nasza logika biznesowa zapytałaby o połowę tego, czego potrzebowała z kontekstu 1, a druga połowa z kontekstu 2. Miało to kilka poważnych problemów. Zamiast wykonać jedno zapytanie w jednym kontekście, musieliśmy wykonać wiele zapytań w różnych kontekstach. Ma to prawdziwy wpływ na wydajność.

W końcu dobrą wiadomością jest to, że łatwo było usunąć wiele kontekstów. Kontekst ma być lekkim przedmiotem. Nie sądzę więc, aby wydajność była dobrym argumentem dla wielu kontekstów. W prawie wszystkich przypadkach uważam, że pojedynczy kontekst jest prostszy, mniej skomplikowany i prawdopodobnie będzie działał lepiej, i nie będziesz musiał wdrożyć wielu obejść, aby go uruchomić.

Pomyślałem o jednej sytuacji, w której przydatne może być wiele kontekstów. Osobny kontekst może być wykorzystany do rozwiązania fizycznego problemu z bazą danych, w której faktycznie zawiera więcej niż jedną domenę. Idealnie byłoby, gdyby kontekst był jeden do jednego dla domeny, który byłby jeden do jednego dla bazy danych. Innymi słowy, jeśli zestaw tabel nie jest w żaden sposób powiązany z innymi tabelami w danej bazie danych, prawdopodobnie powinny zostać wyciągnięte do osobnej bazy danych. Zdaję sobie sprawę, że to nie zawsze jest praktyczne. Ale jeśli zestaw tabel jest tak różny, że możesz czuć się swobodnie, dzieląc je na osobną bazę danych (ale nie chcesz), to mogę zobaczyć argument za użyciem osobnego kontekstu, ale tylko dlatego, że w rzeczywistości istnieją dwie oddzielne domeny.

Jeśli chodzi o mikrousługi, jeden kontekst nadal ma sens. Jednak w przypadku mikrousług każda usługa miałaby swój własny kontekst, który zawiera tylko tabele bazy danych odpowiednie dla tej usługi. Innymi słowy, jeśli usługa x uzyskuje dostęp do tabel 1 i 2, a usługa y uzyskuje dostęp do tabel 3 i 4, każda usługa miałaby swój unikalny kontekst, który obejmuje tabele specyficzne dla tej usługi.

Interesują mnie twoje myśli.

Francisco d'Anconia
źródło
8
Muszę się tutaj zgodzić, szczególnie w przypadku celowania w istniejącą bazę danych. Pracuję teraz nad tym problemem, a moje dotychczasowe przeczucie brzmi: 1. Posiadanie tego samego fizycznego stołu w wielu kontekstach jest złym pomysłem. 2. Jeśli nie możemy zdecydować, że tabela należy do jednego lub innego kontekstu, wówczas dwa konteksty nie są wystarczająco odrębne, aby można je było logicznie oddzielić.
jkerak
3
Argumentowałbym, że robiąc CQRS, nie miałbyś żadnych relacji między kontekstami (każdy widok może mieć swój własny kontekst), więc to ostrzeżenie nie ma zastosowania do każdego przypadku, w którym można chcieć mieć wiele kontekstów. Zamiast łączyć się i odwoływać, używaj duplikacji danych dla każdego kontekstu. - Nie neguje to jednak przydatności tej odpowiedzi :)
urbanhusky
1
Czułam głęboki ból! : / Myślę też, że jeden kontekst jest lepszym wyborem dla uproszczenia.
Ahmet
1
Mój jedyny argument przeciwko, zauważając, że w przeciwnym razie w pełni się zgadzam, dotyczy tożsamości. Zwłaszcza w przypadku skalowania poziomego warstwa tożsamości wymaga oddzielenia w prawie wszystkich przypadkach, w których wprowadzono równoważenie obciążenia. Przynajmniej to znajduję.
Barry
5
Wydaje mi się, że nie korzystałeś z DDD do końca, jeśli twoje agregaty musiały znać inne agregaty. Jeśli musisz coś powołać, istnieją dwa powody: są one w tej samej agregacie, co oznacza, że ​​muszą zostać zmienione w tej samej transakcji, albo nie są, a twoje granice są błędne.
Simons0n
54

Ten wątek właśnie pojawił się na StackOverflow, więc chciałem zaoferować kolejną „B) gwarancję, że wszystko będzie dobrze” :)

Robię to dokładnie za pomocą wzoru ograniczonego kontekstu DDD. Napisałem o tym w mojej książce Programming Entity Framework: DbContext i jest to temat 50-minutowego modułu w jednym z moich kursów na temat Pluralsight -> http://pluralsight.com/training/Courses/TableOfContents/efarchitecture

Julie Lerman
źródło
7
Film szkoleniowy Pluralsight był bardzo dobry w wyjaśnianiu wielkich pojęć, jednak imho, podane przykłady są zbyt trywialne w porównaniu z rozwiązaniem dla przedsiębiorstw (gdzie na przykład istnieją NuGet zestawów z definicjami DbContext lub zespoły modułowe ładują się dynamicznie). Kontekst związany z DDD został całkowicie przerwany przez twój ostatni przykład, w którym zdefiniowano zduplikowany kontekst Db do przechowywania zduplikowanych deklaracji dla każdego zestawu DbSet. Rozumiem, że jesteś ograniczony technologią. Naprawdę lubię twoje filmy, ale ten sprawił, że chciałem więcej.
Victor Romeo
5
Zdecydowanie chciałem uzyskać duży obraz. problemy z pakietami ponownymi w dużych aplikacjach są całkiem poza kontekstem dla filmu ef. Re „zepsute” przykłady ... Hę? Może lepiej zabrać to na prywatny konwój, ponieważ krytyka mojego kursu jest dość poza zakresem (i być może nieodpowiednim) dla tego forum. Myślę, że SO pozwala ci skontaktować się ze mną bezpośrednio.
Julie Lerman
57
Byłoby miło, gdyby Julie podzieliła się informacjami na temat problemu / pytania PO. Zamiast tego post służy jedynie promowaniu płatnej subskrypcji pluralinsight. Jeśli wtyczka do produktu byłaby pomocna, przynajmniej link do informacji o sugerowanym rozwiązaniu (Wzorzec kontekstu ograniczonego DDD). Czy „DDD” jest opisane na str. 222 „Programming Entity Framework: DBContext”? Ponieważ szukałem (bez indeksu) „DDD”, a nawet „Ograniczonego kontekstu” i nie mogę zlokalizować ... Nie mogę się doczekać, aż wprowadzicie nowe poprawki do EF6 ...
Współczujący narcyz
12
przepraszam, nie próbowałem promować, po prostu dodałem do PO „chcę zapewnienia”. Ladislav i inni wykonali świetną robotę ze szczegółami. Próbowałem więc stworzyć coś, co już stworzyłem, i które jest o wiele głębsze, niż mógłbym polegać na SO. Oto inne zasoby, w których omówiłem niektóre z tych zagadnień: msdn.microsoft.com/en-us/magazine/jj883952.aspx & msdn.microsoft.com/en-us/magazine/dn342868.aspx & oredev.org / 2013 / wed-pt-konferencja /…
Julie Lerman
podsumowanie sugestii kodu @JulieLerman patrz moja odpowiedź stackoverflow.com/a/36789520/1586498
OzBob 22.04.16
46

Rozróżnianie kontekstów poprzez ustawienie domyślnego schematu

W EF6 możesz mieć wiele kontekstów, po prostu określ nazwę domyślnego schematu bazy danych w OnModelCreatingmetodzie twojej DbContextklasy pochodnej (gdzie jest konfiguracja Fluent-API). Będzie to działać w EF6:

public partial class CustomerModel : DbContext
{   
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("Customer");

        // Fluent API configuration
    }   
}

W tym przykładzie zostanie użyty „Klient” jako prefiks dla tabel bazy danych (zamiast „dbo”). Co ważniejsze, będzie także poprzedzać __MigrationHistorytabelę (-y), np Customer.__MigrationHistory. Możesz mieć więcej niż jedną __MigrationHistorytabelę w jednej bazie danych, po jednej dla każdego kontekstu. Tak więc zmiany, które wprowadzisz dla jednego kontekstu, nie zadziorą z drugim.

Podczas dodawania migracji określ w pełni kwalifikowaną nazwę swojej klasy konfiguracji (pochodną DbMigrationsConfiguration) jako parametr w add-migrationpoleceniu:

add-migration NAME_OF_MIGRATION -ConfigurationTypeName FULLY_QUALIFIED_NAME_OF_CONFIGURATION_CLASS


Krótkie słowo na temat klawisza kontekstu

Zgodnie z tym artykułem MSDN „ Rozdział - Wiele modeli ukierunkowanych na tę samą bazę danych ” EF 6 prawdopodobnie poradziłby sobie z sytuacją, nawet gdyby MigrationHistoryistniała tylko jedna tabela, ponieważ w tabeli znajduje się kolumna ContextKey do rozróżnienia migracji.

Jednak wolę mieć więcej niż jedną MigrationHistorytabelę, określając domyślny schemat, jak wyjaśniono powyżej.


Korzystanie z oddzielnych folderów migracji

W takim scenariuszu możesz również chcieć pracować z różnymi folderami „Migracja” w swoim projekcie. Możesz odpowiednio skonfigurować DbMigrationsConfigurationklasę pochodną, ​​używając MigrationsDirectorywłaściwości:

internal sealed class ConfigurationA : DbMigrationsConfiguration<ModelA>
{
    public ConfigurationA()
    {
        AutomaticMigrationsEnabled = false;
        MigrationsDirectory = @"Migrations\ModelA";
    }
}

internal sealed class ConfigurationB : DbMigrationsConfiguration<ModelB>
{
    public ConfigurationB()
    {
        AutomaticMigrationsEnabled = false;
        MigrationsDirectory = @"Migrations\ModelB";
    }
}


Podsumowanie

Podsumowując, można powiedzieć, że wszystko jest wyraźnie oddzielone: ​​konteksty, foldery migracji w projekcie i tabele w bazie danych.

Wybrałbym takie rozwiązanie, jeśli istnieją grupy podmiotów, które są częścią większego tematu, ale nie są powiązane (za pomocą kluczy obcych) ze sobą.

Jeśli grupy podmiotów nie mają ze sobą nic wspólnego, stworzyłbym osobną bazę danych dla każdego z nich, a także uzyskałbym do nich dostęp w różnych projektach, prawdopodobnie z jednym kontekstem w każdym projekcie.

Jaskółka oknówka
źródło
Co robisz, gdy musisz zaktualizować 2 podmioty, które są w różnych kontekstach?
sotn
Stworzyłbym nową klasę (usługową), która zna oba konteksty, pomyślę o dobrej nazwie i obowiązkach tej klasy i dokonam tej aktualizacji za pomocą jednej z jej metod.
Martin,
7

Prosty przykład do osiągnięcia poniżej:

    ApplicationDbContext forumDB = new ApplicationDbContext();
    MonitorDbContext monitor = new MonitorDbContext();

Po prostu określ zakres właściwości w głównym kontekście: (służy do tworzenia i utrzymywania bazy danych) Uwaga: Po prostu użyj opcji chronionych: (Obiekt nie jest tutaj ujawniany)

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("QAForum", throwIfV1Schema: false)
    {

    }
    protected DbSet<Diagnostic> Diagnostics { get; set; }
    public DbSet<Forum> Forums { get; set; }
    public DbSet<Post> Posts { get; set; }
    public DbSet<Thread> Threads { get; set; }
    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}

MonitorContext: tutaj ujawnij osobny byt

public class MonitorDbContext: DbContext
{
    public MonitorDbContext()
        : base("QAForum")
    {

    }
    public DbSet<Diagnostic> Diagnostics { get; set; }
    // add more here
}

Model diagnostyczny:

public class Diagnostic
{
    [Key]
    public Guid DiagnosticID { get; set; }
    public string ApplicationName { get; set; }
    public DateTime DiagnosticTime { get; set; }
    public string Data { get; set; }
}

Jeśli chcesz, możesz oznaczyć wszystkie jednostki jako chronione w głównym ApplicationDbContext, a następnie utwórz dodatkowe konteksty dla każdej separacji schematów.

Wszystkie używają tego samego ciągu połączenia, jednak używają osobnych połączeń, więc nie krzyżuj transakcji i zwracaj uwagę na problemy z blokowaniem. Ogólnie twoja separacja projektowa, więc i tak nie powinno się zdarzyć.

Choco
źródło
2
To bardzo pomogło. Kontekst „wtórny” nie musi deklarować wspólnej tabeli. Wystarczy ręcznie dodać jego DbSet<x>definicję. Robię to w częściowym dopasowaniu klasy do tego, co robi Projektant EF.
Glen Little,
Uratowałeś mi wiele bólów głowy, proszę pana! Podałeś konkretne rozwiązanie zamiast zaakceptowanej odpowiedzi. Naprawdę doceniony!
WoIIe
6

Przypomnienie: jeśli łączysz wiele kontekstów, upewnij się, że wycinasz i wklejasz wszystkie funkcje z różnych RealContexts.OnModelCreating()do swojego singlaCombinedContext.OnModelCreating() .

Właśnie zmarnowałem czas na szukanie, dlaczego moje relacje kasowania kasowania nie zostały zachowane, tylko po to, aby odkryć, że nie przeniosłem modelBuilder.Entity<T>()....WillCascadeOnDelete();kodu z mojego prawdziwego kontekstu do mojego połączonego kontekstu.

Ilan
źródło
6
Zamiast wycinać i wklejać, możesz po prostu dzwonić OtherContext.OnModelCreating()z połączonego kontekstu?
AlexFoxGill
4

Mój żołądek powiedział mi to samo, kiedy natknąłem się na ten projekt.

Pracuję na bazie kodu, w której istnieją trzy konteksty dbContext do jednej bazy danych. 2 z 3 kontekstów db są zależne od informacji z 1 kontekstu db, ponieważ obsługuje on dane administracyjne. Ten projekt nałożył ograniczenia na sposób wysyłania zapytań do danych. Natknąłem się na ten problem polegający na tym, że nie można dołączyć do kontekstów dbcontext. Zamiast tego musisz wykonać zapytanie dwóch oddzielnych kontekstów db, a następnie wykonać połączenie w pamięci lub wykonać iterację w obu, aby uzyskać kombinację tych dwóch jako zestaw wyników. Problem polega na tym, że zamiast zapytania o konkretny zestaw wyników ładujesz teraz wszystkie swoje rekordy do pamięci, a następnie łączysz się z dwoma zestawami wyników w pamięci. To może naprawdę spowolnić.

Zadałbym pytanie „tylko dlatego, że możesz, prawda?„W

tym artykule opisano problem związany z tym projektem. Określone wyrażenie LINQ zawiera odwołania do zapytań powiązanych z różnymi kontekstami

Victor J. Garcia
źródło
3
Pracowałem nad dużym systemem, w którym mieliśmy wiele kontekstów. Jedną z rzeczy, które znalazłem, było to, że czasami trzeba było umieszczać ten sam zestaw DbSet w wielu kontekstach. Z jednej strony łamie to pewne obawy dotyczące czystości, ale pozwala na wypełnienie zapytań. W przypadku, gdy istnieją pewne tabele administracyjne, które musisz przeczytać, możesz dodać je do podstawowej klasy DbContext i odziedziczyć je w kontekstach modułów aplikacji. „Rzeczywisty” cel administratora może zostać ponownie zdefiniowany jako „zapewnianie konserwacji tabel administracyjnych”, a nie zapewnianie do nich pełnego dostępu.
JMarsch
1
Co do tego, co jest warte, zawsze zastanawiałem się, czy było warto. Z jednej strony, z osobnymi kontekstami, dla deweloperów, którzy chcą pracować tylko z jednym modułem, jest mniej informacji, a Ty czujesz się bezpieczniej podczas definiowania i korzystania z niestandardowych projekcji (ponieważ nie martwisz się efektami, jakie będzie to miało na inne moduły). Z drugiej strony występują problemy, gdy trzeba udostępniać dane w różnych kontekstach.
JMarsch
1
Nie musisz uwzględniać encji w obu, zawsze możesz uzyskać identyfikatory i wykonać drugie zapytanie w innym kontekście. W przypadku małych systemów jest to złe, w przypadku większych DB / systemów z wieloma programistami spójność struktur wielostołowych jest znacznie większym i trudniejszym problemem niż 2 zapytania.
user1496062
4

Zainspirowany przez [@JulieLerman's DDD MSDN Mag Article 2013] [1]

    public class ShippingContext : BaseContext<ShippingContext>
{
  public DbSet<Shipment> Shipments { get; set; }
  public DbSet<Shipper> Shippers { get; set; }
  public DbSet<OrderShippingDetail> Order { get; set; } //Orders table
  public DbSet<ItemToBeShipped> ItemsToBeShipped { get; set; }
  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    modelBuilder.Ignore<LineItem>();
    modelBuilder.Ignore<Order>();
    modelBuilder.Configurations.Add(new ShippingAddressMap());
  }
}

public class BaseContext<TContext>
  DbContext where TContext : DbContext
{
  static BaseContext()
  {
    Database.SetInitializer<TContext>(null);
  }
  protected BaseContext() : base("DPSalesDatabase")
  {}
}   

„Jeśli robisz nowe prace programistyczne i chcesz, aby Code First utworzył lub przeprowadził migrację bazy danych na podstawie twoich klas, musisz stworzyć„ model Ubera ”za pomocą DbContext, który zawiera wszystkie klasy i relacje potrzebne do zbudować kompletny model reprezentujący bazę danych. Jednak ten kontekst nie może dziedziczyć po BaseContext. ” J L

OzBob
źródło
2

Najpierw w kodzie możesz mieć wiele DBContext i tylko jedną bazę danych. Musisz tylko określić parametry połączenia w konstruktorze.

public class MovieDBContext : DbContext
{
    public MovieDBContext()
        : base("DefaultConnection")
    {

    }
    public DbSet<Movie> Movies { get; set; }
}
Daniel
źródło
Tak, możesz, ale jak możesz wysyłać zapytania do różnych podmiotów z różnych kontekstów db?
Reza
2

Kolejna odrobina „mądrości”. Mam bazę danych, zarówno Internet, jak i aplikację wewnętrzną. Mam kontekst dla każdej twarzy. To pomaga mi zachować zdyscyplinowaną i bezpieczną segregację.

Miguel Delgado
źródło
1

Chcę udostępnić przypadek, w którym myślę, że możliwość posiadania wielu DBContexts w tej samej bazie danych ma sens.

Mam rozwiązanie z dwoma bazami danych. Jeden dotyczy danych domeny oprócz informacji o użytkowniku. Drugi służy wyłącznie do informacji o użytkowniku. Podział ten wynika przede wszystkim z ogólnego rozporządzenia UE o ochronie danych . Dzięki dwóm bazom danych mogę swobodnie przenosić dane domeny (np. Z platformy Azure do mojego środowiska programistycznego), o ile dane użytkownika pozostają w jednym bezpiecznym miejscu.

Teraz dla bazy danych użytkowników zaimplementowałem dwa schematy poprzez EF. Jednym z nich jest domyślny zapewniany przez platformę AspNet Identity. Druga to nasza własna implementacja wszystkiego, co związane jest z użytkownikiem. Wolę to rozwiązanie niż rozszerzenie schematu ApsNet, ponieważ mogę łatwo obsłużyć przyszłe zmiany w AspNet Identity, a jednocześnie separacja wyjaśnia programistom, że „nasza własna informacja o użytkowniku” mieści się w określonym schemacie użytkownika, który zdefiniowaliśmy .

freilebt
źródło
2
W mojej odpowiedzi nie widzę żadnego pytania. Nie zadaję jednego jedynego pytania! Raczej dzielenie się scenariuszem, w którym temat dyskusji ma sens.
freilebt
0

Huh, spędziłem sporo czasu na problemie z osobnymi kontekstami DB dla każdego schematu DB, mam nadzieję, że pomoże to komuś innemu ...

Niedawno zacząłem pracować nad projektem, który miał jedną bazę danych z 3 schematami (pierwsze podejście DB), jedną z nich do zarządzania użytkownikami. Z każdego oddzielnego schematu wyodrębniono kontekst DB. Oczywiście użytkownicy byli również powiązani z innymi schematami, np. schemat KB miał tabelę Temat, który „utworzył”, „ostatnio zmodyfikował” itd. FK do schematu tożsamości, appuser tabeli.

Obiekty te zostały załadowane osobno w języku C #, po pierwsze temat został załadowany z 1 kontekstu, następnie użytkownicy zostali załadowani za pomocą identyfikatorów użytkowników z innego kontekstu db - nieźle, trzeba to naprawić! (podobnie do korzystania z wielu kontekstów db w tej samej bazie danych z EF 6 )

Najpierw próbowałem dodać brakujące instrukcje FK ze schematu tożsamości do schematu KB, do EF modelBuilder w kontekście KB DB. Tak samo, jakby był tylko 1 kontekst, ale oddzieliłem go do 2.

modelBuilder.Entity<Topic>(entity =>
{
  entity.HasOne(d => d.Creator)
    .WithMany(p => p.TopicCreator)
    .HasForeignKey(d => d.CreatorId)
    .HasConstraintName("fk_topic_app_users");

Nie działało, ponieważ kontekst bazy danych kb nie miał żadnych informacji o obiekcie użytkownika, postgres zwrócił błąd relation "AppUsers" does not exist. Instrukcja Select nie zawierała prawidłowych informacji o schemacie, nazwach pól itp.

Prawie się poddałem, ale wtedy zauważyłem przełącznik „-d” podczas działania dotnet ef dbcontext scaffold. Jego skrót od -data-adnotations - Użyj atrybutów, aby skonfigurować model (tam, gdzie to możliwe). Jeśli zostanie pominięty, używany jest tylko płynny interfejs API. Po określeniu tego przełącznika właściwości obiektu zostały zdefiniowane nie w kontekście db OnModelCreating(), ale na samym obiekcie, z atrybutami.

W ten sposób EF uzyskał wystarczające informacje do wygenerowania prawidłowej instrukcji SQL z prawidłowymi nazwami pól i schematami.

TL; DR: oddzielne konteksty DB nie radzą sobie dobrze z relacjami (FK) między nimi, każdy kontekst zawiera tylko informacje o swoich własnych bytach. Po włączeniu opcji „-data-adnotations” dotnet ef dbcontext scaffoldinformacje te nie są przechowywane w każdym osobnym kontekście, ale same obiekty DB.

berserker
źródło