Entity Framework: Eine Datenbank, mehrere DbContexts. Ist das eine schlechte Idee? [geschlossen]


212

Mein bisheriger Eindruck war, dass a DbContextIhre Datenbank darstellen soll. Wenn Ihre Anwendung also eine Datenbank verwendet, möchten Sie nur eine DbContext.

Einige Kollegen möchten jedoch Funktionsbereiche in separate DbContextKlassen aufteilen.

Ich glaube, das kommt von einem guten Ort - dem Wunsch, den Code sauberer zu halten -, aber es scheint volatil zu sein. Mein Bauch sagt mir, dass es eine schlechte Idee ist, aber leider ist mein Bauchgefühl keine ausreichende Voraussetzung für eine Designentscheidung.

Also suche ich:

A) konkrete Beispiele dafür, warum dies eine schlechte Idee sein könnte;

B) versichert, dass dies alles gut funktionieren wird.


Antworten:


167

Sie können mehrere Kontexte für eine einzelne Datenbank haben. Dies kann beispielsweise nützlich sein, wenn Ihre Datenbank mehrere Datenbankschemata enthält und Sie jedes als separaten, eigenständigen Bereich behandeln möchten.

Das Problem ist, wenn Sie zuerst Code zum Erstellen Ihrer Datenbank verwenden möchten - dies kann nur ein einziger Kontext in Ihrer Anwendung. Der Trick hierfür ist normalerweise ein zusätzlicher Kontext, der alle Ihre Entitäten enthält und nur für die Datenbankerstellung verwendet wird. In Ihren realen Anwendungskontexten, die nur Teilmengen Ihrer Entitäten enthalten, muss der Datenbankinitialisierer auf null gesetzt sein.

Es gibt andere Probleme, die bei der Verwendung mehrerer Kontexttypen auftreten - z. B. gemeinsam genutzte Entitätstypen und deren Übergabe von einem Kontext an einen anderen usw. Im Allgemeinen ist es möglich, dass Ihr Design viel sauberer wird und verschiedene Funktionsbereiche voneinander getrennt werden, aber es hat seine eigenen Kosten in zusätzlicher Komplexität.


21
Die Verwendung eines einzelnen Kontexts pro App kann teuer sein, wenn die Anwendung viele Entitäten / Tabellen enthält. Je nach Schema kann es daher auch sinnvoll sein, mehrere Kontexte zu haben.
DarthVader

7
Da ich pluralsight nicht abonniere, fand ich diesen großartigen Artikel von Julie Lerman ( ihren Kommentar ) gut nach dieser Frage
Dave T.

Ich schlage vor, Entity Framework, um mehrere Datenbankkontexte in derselben Datenbank durch Namenskonvention zu unterstützen. Aus diesem Grund habe ich immer noch mein eigenes ORM für modulare Anwendungszwecke geschrieben. Das ist schwer zu glauben, dass es eine einzelne Anwendung zwingt, eine einzelne Datenbank zu verwenden. Besonders in Webfarmen haben Sie eine begrenzte Anzahl von Datenbanken
freewill

Außerdem wurde mir klar, dass Sie Migrationen nur für einen Kontext innerhalb des Projekts über die PM-Konsole aktivieren können.
Piotr Kwiatek

9
@PiotrKwiatek Nicht sicher, ob sich dies zwischen Ihrem Kommentar und jetzt geändert hat, aber Enable-Migrations -ContextTypeName MyContext -MigrationsDirectory Migrations\MyContextMigrationsjetzt funktioniert.
Zack

60

Ich habe diese Antwort vor ungefähr vier Jahren geschrieben und meine Meinung hat sich nicht geändert. Seitdem gab es jedoch bedeutende Entwicklungen im Bereich der Mikrodienste. Ich habe am Ende spezifische Hinweise zu Mikrodiensten hinzugefügt ...

Ich werde gegen die Idee abwägen, mit realer Erfahrung, um meine Stimme zu stützen.

Ich wurde zu einer großen Anwendung weitergeleitet, die fünf Kontexte für eine einzelne Datenbank hatte. Am Ende haben wir alle Kontexte bis auf einen entfernt und sind zu einem einzigen Kontext zurückgekehrt.

Auf den ersten Blick scheint die Idee mehrerer Kontexte eine gute Idee zu sein. Wir können unseren Datenzugriff in Domänen unterteilen und mehrere saubere, leichtgewichtige Kontexte bereitstellen. Klingt nach DDD, oder? Dies würde unseren Datenzugriff vereinfachen. Ein weiteres Argument für die Leistung ist, dass wir nur auf den Kontext zugreifen, den wir benötigen.

In der Praxis teilten viele unserer Tabellen mit dem Anwachsen unserer Anwendung Beziehungen in unseren verschiedenen Kontexten. Beispielsweise erforderten Abfragen an Tabelle A in Kontext 1 auch das Verknüpfen von Tabelle B in Kontext 2.

Dies ließ uns ein paar schlechte Entscheidungen. Wir könnten die Tabellen in den verschiedenen Kontexten duplizieren. Wir haben es versucht. Dies führte zu mehreren Zuordnungsproblemen, einschließlich einer EF-Einschränkung, bei der jede Entität einen eindeutigen Namen haben muss. So kamen wir zu Entitäten mit den Namen Person1 und Person2 in den verschiedenen Kontexten. Man könnte argumentieren, dass dies unsererseits schlechtes Design war, aber trotz unserer besten Bemühungen ist unsere Anwendung auf diese Weise tatsächlich in der realen Welt gewachsen.

Wir haben auch versucht, beide Kontexte abzufragen, um die benötigten Daten zu erhalten. Zum Beispiel würde unsere Geschäftslogik die Hälfte dessen, was sie benötigt, aus Kontext 1 und die andere Hälfte aus Kontext 2 abfragen. Dies hatte einige Hauptprobleme. Anstatt eine Abfrage für einen einzelnen Kontext durchzuführen, mussten mehrere Abfragen in verschiedenen Kontexten durchgeführt werden. Dies hat eine echte Leistungsstrafe.

Am Ende ist die gute Nachricht, dass es einfach war, die verschiedenen Kontexte zu entfernen. Der Kontext soll ein leichtes Objekt sein. Daher denke ich nicht, dass Leistung ein gutes Argument für mehrere Kontexte ist. In fast allen Fällen glaube ich, dass ein einzelner Kontext einfacher, weniger komplex und wahrscheinlich leistungsfähiger ist, und Sie müssen keine Reihe von Workarounds implementieren, um ihn zum Laufen zu bringen.

Ich dachte an eine Situation, in der mehrere Kontexte nützlich sein könnten. Ein separater Kontext kann verwendet werden, um ein physisches Problem mit der Datenbank zu beheben, in der sie tatsächlich mehr als eine Domäne enthält. Im Idealfall wäre ein Kontext eins zu eins zu einer Domäne, der eins zu eins zu einer Datenbank wäre. Mit anderen Worten, wenn eine Reihe von Tabellen in keiner Weise mit den anderen Tabellen in einer bestimmten Datenbank verwandt ist, sollten sie wahrscheinlich in eine separate Datenbank gezogen werden. Mir ist klar, dass dies nicht immer praktisch ist. Aber wenn eine Reihe von Tabellen so unterschiedlich ist, dass Sie sie gerne in eine separate Datenbank aufteilen würden (aber Sie möchten dies nicht tun), könnte ich den Fall für die Verwendung eines separaten Kontexts sehen, aber nur, weil es tatsächlich zwei separate Domänen gibt.

In Bezug auf Mikrodienste ist ein einziger Kontext immer noch sinnvoll. Für Mikrodienste hätte jedoch jeder Dienst seinen eigenen Kontext, der nur die für diesen Dienst relevanten Datenbanktabellen enthält. Mit anderen Worten, wenn Dienst x auf die Tabellen 1 und 2 zugreift und Dienst y auf die Tabellen 3 und 4 zugreift, hat jeder Dienst seinen eigenen eindeutigen Kontext, der für diesen Dienst spezifische Tabellen enthält.

Ich interessiere mich für deine Gedanken.


8
Ich muss hier zustimmen, insbesondere wenn ich auf eine vorhandene Datenbank abziele. Ich arbeite gerade an diesem Problem, und mein Bauchgefühl ist bisher: 1. Es ist eine schlechte Idee, denselben physischen Tisch in mehreren Kontexten zu haben. 2. Wenn wir nicht entscheiden können, ob eine Tabelle in den einen oder anderen Kontext gehört, sind die beiden Kontexte nicht unterschiedlich genug, um logisch getrennt zu werden.
Jkerak

3
Ich würde argumentieren, dass Sie bei CQRS keine Beziehungen zwischen Kontexten haben würden (jede Ansicht könnte ihren eigenen Kontext haben), sodass diese Warnung nicht für jeden Fall gilt, in dem mehrere Kontexte gewünscht werden. Verwenden Sie anstelle des Beitritts und der Referenzierung die Datenduplizierung für jeden Kontext. - Dies
negiert

1
Ich fühlte den Schmerz, dem du tief begegnet bist! : / Ich denke auch, dass ein Kontext aus Gründen der Einfachheit die bessere Wahl ist.
ahmet

1
Mein einziges Argument dagegen, dass ich ansonsten voll und ganz zustimme, betrifft die Identität. Insbesondere bei der horizontalen Skalierung muss die Identitätsschicht in fast allen Fällen, in denen ein Lastausgleich eingeführt wird, getrennt werden. Zumindest finde ich das so.
Barry

5
Mir scheint, Sie sind nicht den ganzen Weg DDD gegangen, wenn Ihre Aggregate andere Aggregate kennen mussten. Wenn Sie auf etwas verweisen müssen, gibt es zwei Gründe: Sie befinden sich im selben Aggregat, was bedeutet, dass sie in derselben Transaktion geändert werden müssen oder nicht, und Sie haben Ihre Grenzen falsch angegeben.
Simons0n

54

Dieser Thread ist gerade auf StackOverflow aufgetaucht und deshalb wollte ich eine weitere "B) Zusicherung geben, dass dies alles in Ordnung sein wird" :)

Ich mache genau das über das DDD Bounded Context-Muster. Ich habe darüber in meinem Buch Programming Entity Framework: DbContext geschrieben und es steht im Mittelpunkt eines 50-minütigen Moduls in einem meiner Kurse zu Pluralsight -> http://pluralsight.com/training/Courses/TableOfContents/efarchitecture


7
Das Pluralsight-Schulungsvideo war sehr gut darin, die großen Konzepte zu erklären. Imho, die Beispiele, die Sie geben, sind im Vergleich zu einer Unternehmenslösung zu trivial (wo beispielsweise NuGet von Assemblys mit DbContext-Definitionen vorhanden ist oder modulare Assemblys dynamisch geladen werden) DDD Bounded Context wurde durch Ihr letztes Beispiel vollständig unterbrochen, in dem ein doppelter DbContext definiert wurde, der doppelte Deklarationen für jedes DbSet enthält. Ich weiß es zu schätzen, dass Sie durch die Technologie eingeschränkt sind. Ich mag deine Videos wirklich, aber dieses hat mich dazu gebracht, mehr zu wollen.
Victor Romeo

5
Ich wollte auf jeden Fall ein großes Bild haben. Probleme mit Nuget-Paketen in Big Apps sind für ein EF-Video ziemlich unzusammenhängend. Re "kaputte" Beispiele ... Huh? Vielleicht ist es besser, dies zur privaten Convo zu bringen, da eine Kritik meines Kurses für dieses Forum ziemlich unangebracht (und möglicherweise unangemessen) ist. Ich denke, SO können Sie mich direkt kontaktieren.
Julie Lerman

57
Es wäre schön gewesen, wenn Julie einige Informationen über das Problem / die Frage des OP geteilt hätte. Stattdessen dient die Post nur dazu, ein kostenpflichtiges Abonnement für pluralinsight zu bewerben. Bei einem Plug für ein Produkt wäre zumindest ein Link zu Informationen zur vorgeschlagenen Lösung (DDD Bounded Context Pattern) hilfreich. Ist 'DDD' das, was auf S.222 von "Programming Entity Framework: DBContext" beschrieben wird? Weil ich (kein Index) nach 'DDD' oder sogar 'Bounded Context' gesucht habe und nicht finden kann ... Ich kann es kaum erwarten, dass Sie neue Revisionen für EF6 vornehmen ...
Compassionate Narcissist

12
Entschuldigung, ich habe nicht versucht zu fördern, sondern nur dem OP "Will Assurances" hinzugefügt. Ladislav und andere haben großartige Arbeit mit Details geleistet. Also habe ich nur versucht, etwas zu tun, das ich bereits erstellt habe und das viel tiefer geht, als ich möglicherweise auf SO weitergeben könnte. Hier sind andere Ressourcen, in denen ich einige der Themen ausführlich behandelt habe: msdn.microsoft.com/en-us/magazine/jj883952.aspx & msdn.microsoft.com/en-us/magazine/dn342868.aspx & oredev.org / 2013 / Mi-Fri-Konferenz /…
Julie Lerman

Zusammenfassung der Codevorschläge von @JulieLerman siehe meine Antwort stackoverflow.com/a/36789520/1586498
OzBob

46

Unterscheiden von Kontexten durch Festlegen des Standardschemas

In EF6 können Sie mehrere Kontexte haben. Geben Sie einfach den Namen für das Standarddatenbankschema in der OnModelCreatingMethode Ihrer DbContextabgeleiteten Klasse an (wo sich die Fluent-API-Konfiguration befindet). Dies funktioniert in EF6:

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

        // Fluent API configuration
    }   
}

In diesem Beispiel wird "Kunde" als Präfix für Ihre Datenbanktabellen verwendet (anstelle von "dbo"). Noch wichtiger ist, dass auch die __MigrationHistoryTabelle (n) vorangestellt wird , z Customer.__MigrationHistory. Sie können also mehr als eine __MigrationHistoryTabelle in einer einzelnen Datenbank haben, eine für jeden Kontext. Die Änderungen, die Sie für einen Kontext vornehmen, wirken sich also nicht auf den anderen aus.

Geben Sie beim Hinzufügen der Migration den vollständig qualifizierten Namen Ihrer Konfigurationsklasse (abgeleitet von DbMigrationsConfiguration) als Parameter im add-migrationBefehl an:

add-migration NAME_OF_MIGRATION -ConfigurationTypeName FULLY_QUALIFIED_NAME_OF_CONFIGURATION_CLASS


Ein kurzes Wort zum Kontextschlüssel

Laut diesem MSDN-Artikel " Kapitel - Mehrere Modelle, die auf dieselbe Datenbank abzielen " würde EF 6 die Situation wahrscheinlich auch dann behandeln, wenn nur eine MigrationHistoryTabelle vorhanden wäre, da in der Tabelle eine ContextKey- Spalte zur Unterscheidung der Migrationen vorhanden ist.

Ich bevorzuge jedoch mehr als eine MigrationHistoryTabelle, indem ich das oben erläuterte Standardschema spezifiziere.


Verwenden separater Migrationsordner

In einem solchen Szenario möchten Sie möglicherweise auch mit verschiedenen "Migrations" -Ordnern in Ihrem Projekt arbeiten. Sie können Ihre DbMigrationsConfigurationabgeleitete Klasse mithilfe der MigrationsDirectoryEigenschaft entsprechend einrichten :

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";
    }
}


Zusammenfassung

Alles in allem kann man sagen, dass alles sauber getrennt ist: Kontexte, Migrationsordner im Projekt und Tabellen in der Datenbank.

Ich würde eine solche Lösung wählen, wenn es Gruppen von Entitäten gibt, die Teil eines größeren Themas sind, aber nicht (über Fremdschlüssel) miteinander verbunden sind.

Wenn die Gruppen von Entitäten nichts miteinander zu tun haben, würde ich für jede von ihnen eine separate Datenbank erstellen und auch in verschiedenen Projekten darauf zugreifen, wahrscheinlich mit einem einzigen Kontext in jedem Projekt.


Was tun Sie, wenn Sie zwei Entitäten aktualisieren müssen, die sich in unterschiedlichen Kontexten befinden?
SOTN

Ich würde eine neue (Dienst-) Klasse erstellen, die beide Kontexte kennt, über einen guten Namen und die Verantwortlichkeiten dieser Klasse nachdenken und dieses Update in einer ihrer Methoden durchführen.
Martin

7

Einfaches Beispiel, um Folgendes zu erreichen:

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

Bereich einfach die Eigenschaften im Hauptkontext: (wird zum Erstellen und Verwalten der Datenbank verwendet) Hinweis: Verwenden Sie einfach protected: (Entität ist hier nicht verfügbar)

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: Stellen Sie hier eine separate Entität bereit

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

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

Diagnosemodell:

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

Wenn Sie möchten, können Sie alle Entitäten im Haupt-ApplicationDbContext als geschützt markieren. Erstellen Sie dann nach Bedarf zusätzliche Kontexte für jede Trennung von Schemas.

Sie alle verwenden dieselbe Verbindungszeichenfolge, verwenden jedoch separate Verbindungen. Überkreuzen Sie also keine Transaktionen und achten Sie auf Sperrprobleme. Im Allgemeinen ist Ihre Design-Trennung so, dass dies sowieso nicht passieren sollte.


2
Das hat sehr geholfen. Der "sekundäre" Kontext muss die gemeinsam genutzte Tabelle nicht deklarieren. Fügen Sie einfach manuell die DbSet<x>Definition hinzu. Ich mache das in einer Teilklasse, die dem entspricht, was der EF Designer macht.
Glen Little

Sie haben mir viele Kopfschmerzen erspart, Sir! Sie haben anstelle der akzeptierten Antwort eine konkrete Lösung angegeben. Sehr geschätzt!
WoIIe

6

Erinnerung: Wenn Sie mehrere Kontexte kombinieren, stellen Sie sicher, dass Sie alle Funktionen in Ihren verschiedenen Kontexten ausschneiden und RealContexts.OnModelCreating()in Ihre einzelne einfügen CombinedContext.OnModelCreating().

Ich habe nur Zeit damit verschwendet, herauszufinden, warum meine Kaskaden-Löschbeziehungen nicht beibehalten wurden, nur um festzustellen, dass ich den modelBuilder.Entity<T>()....WillCascadeOnDelete();Code nicht aus meinem realen Kontext in meinen kombinierten Kontext portiert hatte .


6
Könnten Sie statt Ausschneiden und Einfügen einfach OtherContext.OnModelCreating()aus Ihrem kombinierten Kontext aufrufen ?
AlexFoxGill

4

Mein Bauch sagte mir dasselbe, als ich auf dieses Design stieß.

Ich arbeite an einer Codebasis, in der eine Datenbank drei dbContexts enthält. 2 der 3 Datenbankkontexte sind abhängig von Informationen aus 1 Datenbankkontext, da sie die Verwaltungsdaten bereitstellen. Dieses Design hat Einschränkungen auferlegt, wie Sie Ihre Daten abfragen können. Ich bin auf dieses Problem gestoßen, bei dem Sie nicht über Datenbankkontexte hinweg beitreten können. Stattdessen müssen Sie die beiden separaten Datenbankkontexte abfragen und dann einen Join im Speicher durchführen oder beide durchlaufen, um die Kombination der beiden als Ergebnismenge zu erhalten. Das Problem dabei ist, dass Sie nicht nach einer bestimmten Ergebnismenge abfragen, sondern jetzt alle Ihre Datensätze in den Speicher laden und dann einen Join für die beiden Ergebnismengen im Speicher durchführen. Es kann die Dinge wirklich verlangsamen.

Ich würde die Frage stellen "Nur weil du kannst, solltest du?"In

diesem Artikel finden Sie das Problem, das bei diesem Entwurf aufgetreten ist . Der angegebene LINQ-Ausdruck enthält Verweise auf Abfragen, die verschiedenen Kontexten zugeordnet sind


3
Ich habe an einem großen System gearbeitet, in dem wir mehrere Kontexte hatten. Eines der Dinge, die ich fand, war, dass man manchmal dasselbe DbSet in mehrere Kontexte einbinden musste. Auf der einen Seite werden dadurch einige Bedenken hinsichtlich der Reinheit ausgeräumt, aber Sie können Ihre Abfragen abschließen. In einem Fall, in dem bestimmte Admin-Tabellen gelesen werden müssen, können Sie sie einer Basis-DbContext-Klasse hinzufügen und in Ihren App-Modul-Kontexten erben. Der Zweck Ihres "echten" Administratorkontexts wird möglicherweise als "Wartung für Admin-Tabellen bereitstellen" neu definiert, anstatt den gesamten Zugriff darauf bereitzustellen.
JMarsch

1
Für das, was es wert ist, ging ich immer hin und her, ob es das wert war. Einerseits gibt es in einem separaten Kontext weniger zu wissen für einen Entwickler, der nur an einem Modul arbeiten möchte, und Sie fühlen sich sicherer, wenn Sie benutzerdefinierte Projektionen definieren und verwenden (weil Sie sich keine Sorgen über die Auswirkungen machen, die dies auf andere haben wird Module). Auf der anderen Seite treten einige Probleme auf, wenn Sie Daten kontextübergreifend freigeben müssen.
JMarsch

1
Sie MÜSSEN keine Entitäten in beide einschließen. Sie können jederzeit die IDs abrufen und eine zweite Abfrage in einem anderen Kontext durchführen. Für kleine Systeme ist dies schlecht, für größere DBs / Systeme mit vielen Entwicklern ist die Kohärenz von Multi-Table-Strukturen ein viel größeres und schwierigeres Problem als 2 Abfragen.
user1496062

4

Inspiriert von [@JulieLermans 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")
  {}
}   

"Wenn Sie eine Neuentwicklung durchführen und Code First Ihre Datenbank basierend auf Ihren Klassen erstellen oder migrieren lassen möchten, müssen Sie ein" Übermodell "mit einem DbContext erstellen, der alle erforderlichen Klassen und Beziehungen enthält Erstellen Sie ein vollständiges Modell, das die Datenbank darstellt. Dieser Kontext darf jedoch nicht von BaseContext erben. " J L


2

Im Code zuerst können Sie mehrere DBContext und nur eine Datenbank haben. Sie müssen nur die Verbindungszeichenfolge im Konstruktor angeben.

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

    }
    public DbSet<Movie> Movies { get; set; }
}

Ja, das können Sie, aber wie können Sie von verschiedenen Entitäten aus verschiedenen Datenbankkontexten abfragen?
Reza

2

Noch ein bisschen "Weisheit". Ich habe eine Datenbank mit Blick auf das Internet und eine interne App. Ich habe einen Kontext für jedes Gesicht. Das hilft mir, eine disziplinierte, sichere Trennung aufrechtzuerhalten.


1

Ich möchte einen Fall teilen, in dem die Möglichkeit, mehrere DBContexts in derselben Datenbank zu haben, meiner Meinung nach sinnvoll ist.

Ich habe eine Lösung mit zwei Datenbanken. Eine ist für Domänendaten außer Benutzerinformationen. Die andere dient ausschließlich der Benutzerinformation. Diese Aufteilung wird hauptsächlich durch die EU -Datenschutzgrundverordnung bestimmt . Durch zwei Datenbanken kann ich die Domänendaten frei verschieben (z. B. von Azure in meine Entwicklungsumgebung), solange sich die Benutzerdaten an einem sicheren Ort befinden.

Jetzt habe ich für die Benutzerdatenbank zwei Schemas über EF implementiert. Eine ist die Standardeinstellung, die vom AspNet Identity-Framework bereitgestellt wird. Das andere ist unsere eigene Implementierung von allem, was mit dem Benutzer zu tun hat. Ich bevorzuge diese Lösung gegenüber der Erweiterung des ApsNet-Schemas, da ich zukünftige Änderungen an der AspNet-Identität problemlos verarbeiten kann und gleichzeitig den Programmierern durch die Trennung klar wird, dass "unsere eigenen Benutzerinformationen" in dem von uns definierten spezifischen Benutzerschema enthalten sind .


2
Ich sehe keine Frage in meiner Antwort. Ich stelle keine einzige Frage! Teilen Sie lieber ein Szenario, in dem das Diskussionsthema sinnvoll ist.
freilebt

0

Huh, ich habe ziemlich viel Zeit mit einem Problem mit separaten DB-Kontexten für jedes DB-Schema verbracht und hoffe, dass es jemand anderem hilft ...

Ich habe kürzlich begonnen, an einem Projekt zu arbeiten, das eine Datenbank mit 3 Schemas (DB First Approach) hatte, eines davon für die Benutzerverwaltung. Es gab ein DB-Kontextgerüst aus jedem einzelnen Schema. Natürlich waren Benutzer auch mit anderen Schemata verwandt, z. Schema KB hatte ein Tabellenthema, das "erstellt von", "zuletzt geändert von" usw. FK zum Identitätsschema, Tabellenbenutzer.

Diese Objekte wurden separat in C # geladen. Zuerst wurde das Thema aus einem Kontext geladen, dann wurden die Benutzer über Benutzer-IDs aus dem anderen Datenbankkontext geladen - nicht schön, müssen dies beheben! (Ähnlich wie bei der Verwendung mehrerer Datenbankkontexte in derselben Datenbank mit EF 6 )

Zuerst habe ich versucht, fehlende FK-Anweisungen aus dem Identitätsschema zum KB-Schema und zum EF modelBuilder im KB DB-Kontext hinzuzufügen. Das gleiche, als gäbe es nur einen Kontext, aber ich habe ihn in zwei getrennt.

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

Es hat nicht funktioniert, da kb db context keine Informationen über das Benutzerobjekt hatte, hat postgres einen Fehler zurückgegeben relation "AppUsers" does not exist. Die Select-Anweisung hatte keine richtigen Informationen zu Schema, Feldnamen usw.

Ich hätte fast aufgegeben, aber dann bemerkte ich beim Laufen einen Schalter "-d" dotnet ef dbcontext scaffold. Die Abkürzung für -data-annotations - Verwenden Sie Attribute, um das Modell zu konfigurieren (sofern möglich). Wenn nicht angegeben, wird nur die fließende API verwendet. Mit diesem Schalter wurden Objekteigenschaften nicht im Datenbankkontext definiert OnModelCreating(), sondern auf dem Objekt selbst mit Attributen.

Auf diese Weise erhielt EF ausreichende Informationen zum Generieren einer richtigen SQL-Anweisung mit richtigen Feldnamen und Schemas.

TL; DR: Separate DB-Kontexte verarbeiten Beziehungen (FKs) zwischen ihnen nicht gut. Jeder Kontext enthält nur Informationen zu seinen eigenen Entitäten. Wenn Sie "-data-annotations" angeben dotnet ef dbcontext scaffold, werden diese Informationen nicht in jedem separaten Kontext, sondern in DB-Objekten selbst gespeichert.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.