EF Core unico DbContext per database multischema

di il
8 risposte

EF Core unico DbContext per database multischema

Vediamo quanto siete bravi.

[Contesto]
Ho un database SQL Server che chiameremo Database1, le cui tabelle sono organizzate in Schemi che chiameremo Schema1, Schema2,..

Sto usando l'estensione EF Core Power Tools per Visual Studio per fare il reverse engineering del database con "sbattimento zero" cosa che apprezzo sempre.

Il tool riesce a generare il DbContext, crea la cartella Models con le subfolder per gli schemi e con dentro le Entità.
Abbiamo quindi:
/Models/Schema1/Tabella1.cs
/Models/Schema1/Tabella2.cs
/Models/Schema2/Tabella1.cs
/Models/Schema2/Tabella2.cs

La mappatura riesce correttamente perche viene utilizzato nella configurazione: entity.ToTable("Tabella1", "schema1");

[Desiderato]
Vorrei poter accedere alle entità con Database1Context.Schema1.Tabella1 anzichè "Database1Context.Tabella1" in modo da rispettare l'organizzazione in schemi del database e poter gestire tabelle con lo stesso nome.

Guai a chi mi dice di usare un DbContext per Schema (potrei abusare della mia posizione di moderatore)

8 Risposte

  • Re: EF Core unico DbContext per database multischema

    Toki ha scritto:


    Vorrei poter accedere alle entità con Database1Context.Schema1.Tabella1 anzichè "Database1Context.Tabella1" in modo da rispettare l'organizzazione in schemi del database e poter gestire tabelle con lo stesso nome.
    In pratica, se ho capito bene, vorresti generare le classi partendo dal database in modo che nel namespace venga inserita l'informazione dello Schema, come fosse un livello in più nella gerarchia di classi, e tutto questo gestito da un singolo DbContext?

    Che io sappia, quanto chiedi non è supportato da EF ma vi sono dei motivi validi: tu dici di non voler usare due contesti, ma se nei due Schema hai due tabelle con lo stesso nome, essendo che il DbContext ti permette di accedere alla tabella tramite una proprietà omonima, come fai ad avere due proprietà senza dire a quale schema fa riferimento ciascuna di esse: non potranno mai avere lo stesso nome, che tu decida di sparare o no.

    Se il nome deve essere reso "disambiguo", allora è necessario per forza un intervento manuale e sfuma così il valore della generazione automatica.

    Non vedrei comunque la problematica di usare due DbContext: alla fine è un DAL, un servizio implementativo come un altro, che io istanzio analogamente agli altri oggetti (usando la DI), e avere una suddivisione può addittura farti comodo.

    Ciao!
  • Re: EF Core unico DbContext per database multischema

    Alka ha scritto:


    Se il nome deve essere reso "disambiguo", allora è necessario per forza un intervento manuale e sfuma così il valore della generazione automatica.
    Il nome deve essere disambiguo ma non è un particolare problema, è facilmente gestibile.
    Mi chiedevo invece se c'era appunto qualcosa che mi fosse sfuggito del tool EF Core Power Tools e delle opzioni di scaffolding in generale che permettessero una perfetta suddivisione delle entità in namespace differenti a rappresentarne gli schemi di provenienza.

    Toki ha scritto:


    Non vedrei comunque la problematica di usare due DbContext: alla fine è un DAL, un servizio implementativo come un altro, che io istanzio analogamente agli altri oggetti (usando la DI), e avere una suddivisione può addittura farti comodo.
    Devo poter fare delle query LINQ che mettono in relazione tabelle di schemi differenti.
    In questo caso le ritroverei mappate su Entità che risiedono in DbContext differenti.
  • Re: EF Core unico DbContext per database multischema

    Toki ha scritto:


    Mi chiedevo invece se c'era appunto qualcosa che mi fosse sfuggito del tool EF Core Power Tools e delle opzioni di scaffolding in generale che permettessero una perfetta suddivisione delle entità in namespace differenti a rappresentarne gli schemi di provenienza.
    Cercando in giro, io non ho trovato nulla di specifico riguardo questo ambito particolare.

    Toki ha scritto:


    Devo poter fare delle query LINQ che mettono in relazione tabelle di schemi differenti.
    In questo caso le ritroverei mappate su Entità che risiedono in DbContext differenti.
    Effettivamente, questo scenario sarebbe una problematica.
    Tuttavia, alla peggio si può sempre ricorrere a una bella vista o stored classica...

    Ciao!
  • Re: EF Core unico DbContext per database multischema

    Alka ha scritto:


    Tuttavia, alla peggio si può sempre ricorrere a una bella vista o stored classica...
    Ci sono già quelle necessarie, preferisco non farle proliferare ulteriormente.

    Grazie comunque per il tempo che mi hai dedicato
  • Re: EF Core unico DbContext per database multischema

    Ciao

    Non so se possa essere una alternativa valida, però potresi:
    • Creare una classe Schema1 che prende un DbContext nel costruttore ed espone le tabelle che i servono (c'è la proprietà la cui implementazione di fatto è un rimando a DbContext.Tabella
    • Allo stesso modo fai la classe Schema2
    • Crei un nuovo DbContext che prende nel costruttore il DbContext autogenerato, poi le tabelle dello schema1 le espone tramite la proprietà Schema1, lo stesso per lo Schema2, le altre le disponi come sono. Questa classe la puoi anche autogenerare con un tool se vuoi

    Non so se ho reso l'idea
  • Re: EF Core unico DbContext per database multischema

    Ciao,
    non so se ho capito bene la tua proposta però mi sembra di capire che avrei comunque più DbContext e la problematica delle query LINQ che mettono in relazione tabelle di schemi e quindi DbContext differenti.
    Mi sono perso qualcosa?
  • Re: EF Core unico DbContext per database multischema

    Forse mi sono spiegato male (rileggendo probabilmente è così) ma di DbContext ne hai uno solo, quello autogenerato.

    L'altro DbContext di cui parlavo è una classe "normale" che espone solo i metodi che ti servono.
    Butto giù due righe al volo, non guardare gli errori di sintassi ma prendi il concetto..
    
    
    // Autogenerato dal tool che stai usando
    public class DbContextAutogenerato 
    {
    
        // Schema 1
        public DbSet<Tabella1> Tabella1 { get; set; }
        
        // Schema 2
        public DbSet<Tabella2> Tabella2 { get; set; }
        
        // Schema dbo
        public DbSet<Tabella3> Tabella3 { get; set; }
    }
    
    
    // Da qui in poi, o scrivi le classi a mano, oppure ti fai un tool.. ci vuole poco se hai le regole
    
    
    public class Schema1 
    {
    
       public void Schema1(DbContextAutogenerato context) 
       {
           Db = context ?? throw new ArgumentNullException(nameof(context));
       }
       
       
       private DbContextAutogenerato Db { get; }
       
       public DbSet<Tabella1> Tabella1 
       {
          get 
          {
             return Db.Tabella1;
          }
       }
    }
    
    
    public class Schema2 
    {
    
       public void Schema2(DbContextAutogenerato context) 
       {
           Db = context ?? throw new ArgumentNullException(nameof(context));
       }
       
       
       private DbContextAutogenerato Db { get; }
       
       public DbSet<Tabella2> Tabella2 
       {
          get 
          {
             return Db.Tabella2;
          }
       }
    }
    
    
    
    // Nel tuo programma usi questo Db (se usi la dependency injection ti viene quasi gratis)
    public class MyDatabase
    {
    
       public void MyDatabase(DbContextAutogenerato context) 
       {
           Db = context ?? throw new ArgumentNullException(nameof(context));
           Schema1 = new Schema1(context);
           Schema2 = new Schema2(context);
       }
       
       
       public Schema1 Schema1 { get; }
       
       public Schema2 Schema2 { get; }
       
       private DbContextAutogenerato Db { get; }
       
       public DbSet<Tabella3> Tabella3
       {
          get 
          {
             return Db.Tabella3;
          }
       }
       
       
       // Ricordati i metodi comuni che ti servono per gli aggiornamenti
       public int SaveChanges() 
       {
          Db.SaveChanges();
       }
    }
    
    
    
    Non so se ora sono stato più chiaro.
  • Re: EF Core unico DbContext per database multischema

    Ciao, grazie per la bozza di codice.
    Devo provarlo ma ad occhio potrebbe essere la soluzione al problema
Devi accedere o registrarti per scrivere nel forum
8 risposte