Condividi tramite


Modifiche di rilievo in EF Core 7.0 (EF7)

Questa pagina illustra le modifiche di comportamento e API che potrebbero interrompere l'aggiornamento delle applicazioni esistenti da EF Core 6 a EF Core 7. Assicurarsi di esaminare le modifiche di rilievo precedenti se si esegue l'aggiornamento da una versione precedente di EF Core:

Framework di destinazione

EF Core 7.0 è destinato a .NET 6. Ciò significa che le applicazioni esistenti destinate a .NET 6 possono continuare a farlo. Le applicazioni destinate a versioni precedenti di .NET, .NET Core e .NET Framework dovranno usare .NET 6 o .NET 7 per usare EF Core 7.0.

Riepilogo

Modifica di rilievo Impatto
Encrypt per impostazione predefinita per true le connessioni di SQL Server Alto
Alcuni avvisi genereranno di nuovo eccezioni per impostazione predefinita Alto
Le tabelle di SQL Server con trigger o determinate colonne calcolate richiedono ora una configurazione speciale di EF Core Alto
Le tabelle SQLite con trigger AFTER e tabelle virtuali richiedono ora una configurazione speciale di EF Core Alto
Le dipendenze orfane delle relazioni facoltative non vengono eliminate automaticamente Medio
L'eliminazione a catena viene configurata tra tabelle quando si usa il mapping TPT con SQL Server Medio
Maggiore probabilità di errori occupati/bloccati in SQLite quando non si usa la registrazione write-ahead Medio
Potrebbe essere necessario configurare le proprietà chiave con un operatore di confronto dei valori del provider Basso
I vincoli Check e altri facet di tabella sono ora configurati nella tabella Basso
Gli spostamenti dalle nuove entità alle entità eliminate non vengono risolti Basso
L'uso FromSqlRaw e i metodi correlati dal provider errato generano un'eccezione Basso
Scaffolding OnConfiguring non più chiamate IsConfigured Basso

Modifiche ad alto impatto

Encrypt per impostazione predefinita per true le connessioni di SQL Server

Problema di rilevamento: SqlClient #1210

Importante

Si tratta di una modifica di rilievo grave nel pacchetto Microsoft.Data.SqlClient . Non è possibile eseguire alcuna operazione in EF Core per ripristinare o attenuare questa modifica. Inviare commenti e suggerimenti al repository GitHub Microsoft.Data.SqlClient oppure contattare un supporto tecnico Microsoft Professional per ulteriori domande o assistenza.

Comportamento precedente

SqlClient stringa di connessione usa per Encrypt=False impostazione predefinita. Ciò consente le connessioni nei computer di sviluppo in cui il server locale non dispone di un certificato valido.

Nuovo comportamento

SqlClient stringa di connessione usa per Encrypt=True impostazione predefinita. Ciò significa che:

  • Il server deve essere configurato con un certificato valido
  • Il client deve considerare attendibile questo certificato

Se queste condizioni non vengono soddisfatte, verrà generata un'eccezione SqlException . Ad esempio:

È stata stabilita una connessione con il server, ma si è verificato un errore durante il processo di accesso. (provider: provider SSL, errore: 0: la catena di certificati è stata emessa da un'autorità non attendibile)

Perché

Questa modifica è stata apportata per assicurarsi che, per impostazione predefinita, la connessione sia sicura o che l'applicazione non riesca a connettersi.

Soluzioni di prevenzione

Esistono tre modi per procedere:

  1. Installare un certificato valido nel server. Si noti che si tratta di un processo coinvolto e richiede di ottenere un certificato e di assicurarsi che sia firmato da un'autorità attendibile dal client.
  2. Se il server dispone di un certificato, ma non è considerato attendibile dal client, TrustServerCertificate=True per consentire di ignorare il normale meccanismo di attendibilità.
  3. Aggiungere Encrypt=False in modo esplicito al stringa di connessione.

Avviso

Le opzioni 2 e 3 lasciano il server in uno stato potenzialmente non sicuro.

Alcuni avvisi generano nuovamente eccezioni per impostazione predefinita

Problema di rilevamento n. 29069

Comportamento precedente

In EF Core 6.0, un bug nel provider SQL Server significava che alcuni avvisi configurati per generare eccezioni per impostazione predefinita venivano registrati ma non generavano eccezioni. Questi avvisi sono:

EventId Descrizione
RelationalEventId.AmbientTransactionWarning È possibile che un'applicazione abbia previsto che venga usata una transazione di ambiente quando è stata effettivamente ignorata.
RelationalEventId.IndexPropertiesBothMappedAndNotMappedToTable Un indice specifica le proprietà di cui è stato eseguito il mapping e alcune delle quali non sono mappate a una colonna in una tabella.
RelationalEventId.IndexPropertiesMappedToNonOverlappingTables Un indice specifica le proprietà di cui viene eseguito il mapping alle colonne in tabelle non sovrapposte.
RelationalEventId.ForeignKeyPropertiesMappedToUnrelatedTables Una chiave esterna specifica le proprietà che non eseguono il mapping alle tabelle correlate.

Nuovo comportamento

A partire da EF Core 7.0, questi avvisi, per impostazione predefinita, generano un'eccezione.

Perché

Si tratta di problemi che indicano molto probabilmente un errore nel codice dell'applicazione che deve essere risolto.

Soluzioni di prevenzione

Consente di risolvere il problema sottostante che è il motivo dell'avviso.

In alternativa, il livello di avviso può essere modificato in modo che venga registrato solo o eliminato completamente. Ad esempio:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .ConfigureWarnings(b => b.Ignore(RelationalEventId.AmbientTransactionWarning));

Le tabelle di SQL Server con trigger o determinate colonne calcolate richiedono ora una configurazione speciale di EF Core

Problema di rilevamento n. 27372

Comportamento precedente

Le versioni precedenti del provider SQL Server hanno salvato le modifiche tramite una tecnica meno efficiente che funzionava sempre.

Nuovo comportamento

Per impostazione predefinita, EF Core salva ora le modifiche tramite una tecnica significativamente più efficiente; purtroppo questa tecnica non è supportata in SQL Server se la tabella di destinazione include trigger di database o determinati tipi di colonne calcolate. Per altri dettagli, vedere la documentazione di SQL Server.

Perché

I miglioramenti delle prestazioni collegati al nuovo metodo sono sufficientemente significativi da renderli importanti per gli utenti per impostazione predefinita. Allo stesso tempo, si stima che l'utilizzo dei trigger di database o delle colonne calcolate interessate nelle applicazioni EF Core sia sufficientemente basso che le conseguenze negative delle modifiche di rilievo siano superiori al miglioramento delle prestazioni.

Soluzioni di prevenzione

A partire da EF Core 8.0, l'uso o meno della clausola "OUTPUT" può essere configurato in modo esplicito. Ad esempio:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable(tb => tb.UseSqlOutputClause(false));
}

In EF7 o versioni successive, se la tabella di destinazione ha un trigger, è possibile comunicare a EF Core questo comportamento e EF tornerà alla tecnica precedente meno efficiente. Questa operazione può essere eseguita configurando il tipo di entità corrispondente come indicato di seguito:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable(tb => tb.HasTrigger("SomeTrigger"));
}

Si noti che questa operazione non comporta effettivamente la creazione o la gestione del trigger da parte di EF Core. Attualmente comunica solo a EF Core che i trigger sono presenti nella tabella. Di conseguenza, è possibile usare qualsiasi nome di trigger. È possibile specificare un trigger per ripristinare il comportamento precedente anche se non è effettivamente presente un trigger nella tabella.

Se la maggior parte o tutte le tabelle hanno trigger, è possibile rifiutare esplicitamente di usare la tecnica più recente ed efficiente per tutte le tabelle del modello usando la convenzione di compilazione del modello seguente:

public class BlankTriggerAddingConvention : IModelFinalizingConvention
{
    public virtual void ProcessModelFinalizing(
        IConventionModelBuilder modelBuilder,
        IConventionContext<IConventionModelBuilder> context)
    {
        foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
        {
            var table = StoreObjectIdentifier.Create(entityType, StoreObjectType.Table);
            if (table != null
                && entityType.GetDeclaredTriggers().All(t => t.GetDatabaseName(table.Value) == null)
                && (entityType.BaseType == null
                    || entityType.GetMappingStrategy() != RelationalAnnotationNames.TphMappingStrategy))
            {
                entityType.Builder.HasTrigger(table.Value.Name + "_Trigger");
            }

            foreach (var fragment in entityType.GetMappingFragments(StoreObjectType.Table))
            {
                if (entityType.GetDeclaredTriggers().All(t => t.GetDatabaseName(fragment.StoreObject) == null))
                {
                    entityType.Builder.HasTrigger(fragment.StoreObject.Name + "_Trigger");
                }
            }
        }
    }
}

Usare la convenzione per l'oggetto DbContext eseguendo l'override di ConfigureConventions:

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Conventions.Add(_ => new BlankTriggerAddingConvention());
}

Questa operazione chiama HasTrigger in modo efficace tutte le tabelle del modello, invece di doverla eseguire manualmente per ogni tabella e ogni tabella.

Le tabelle SQLite con trigger AFTER e tabelle virtuali richiedono ora una configurazione speciale di EF Core

Problema di rilevamento n. 29916

Comportamento precedente

Le versioni precedenti del provider SQLite hanno salvato le modifiche tramite una tecnica meno efficiente che funzionava sempre.

Nuovo comportamento

Per impostazione predefinita, EF Core salva ora le modifiche tramite una tecnica più efficiente, usando la clausola RETURNING. Sfortunatamente, questa tecnica non è supportata in SQLite se la tabella di destinazione include trigger AFTER del database, è virtuale o se vengono usate versioni precedenti di SQLite. Per altri dettagli, vedere la documentazione di SQLite.

Perché

Per impostazione predefinita, le semplificazioni e i miglioramenti delle prestazioni collegati al nuovo metodo sono sufficientemente importanti da renderli agli utenti. Allo stesso tempo, si stima che l'utilizzo dei trigger di database e delle tabelle virtuali nelle applicazioni EF Core sia sufficientemente basso che le conseguenze negative delle modifiche di rilievo siano superiori al miglioramento delle prestazioni.

Soluzioni di prevenzione

In EF Core 8.0 il UseSqlReturningClause metodo è stato introdotto per ripristinare in modo esplicito sql meno efficiente e meno efficiente. Ad esempio:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable(tb => tb.UseSqlReturningClause(false));
}

Se si usa ancora EF Core 7.0, è possibile ripristinare il meccanismo precedente per l'intera applicazione inserendo il codice seguente nella configurazione del contesto:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlite(...)
        .ReplaceService<IUpdateSqlGenerator, SqliteLegacyUpdateSqlGenerator>();

Modifiche a impatto medio

Le dipendenze orfane delle relazioni facoltative non vengono eliminate automaticamente

Problema di rilevamento n. 27217

Comportamento precedente

Una relazione è facoltativa se la chiave esterna è nullable. L'impostazione della chiave esterna su Null consente l'esistenza dell'entità dipendente senza alcuna entità principale correlata. Le relazioni facoltative possono essere configurate per l'uso di eliminazioni a catena, anche se non è l'impostazione predefinita.

Un dipendente facoltativo può essere rimosso dalla relativa entità impostando la relativa chiave esterna su Null oppure cancellando la navigazione da o verso di essa. In EF Core 6.0, ciò causerebbe l'eliminazione del dipendente quando la relazione è stata configurata per l'eliminazione a catena.

Nuovo comportamento

A partire da EF Core 7.0, il dipendente non viene più eliminato. Si noti che se l'entità viene eliminata, il dipendente verrà comunque eliminato perché le eliminazioni a catena sono configurate per la relazione.

Perché

Il dipendente può esistere senza alcuna relazione con un'entità di sicurezza, pertanto non è consigliabile eliminare l'entità.

Soluzioni di prevenzione

Il dipendente può essere eliminato in modo esplicito:

context.Remove(blog);

Oppure SaveChanges può essere sottoposto a override o intercettato per eliminare dipendenti senza riferimenti all'entità. Ad esempio:

context.SavingChanges += (c, _) =>
    {
        foreach (var entry in ((DbContext)c!).ChangeTracker
            .Entries<Blog>()
            .Where(e => e.State == EntityState.Modified))
        {
            if (entry.Reference(e => e.Author).CurrentValue == null)
            {
                entry.State = EntityState.Deleted;
            }
        }
    };

L'eliminazione a catena viene configurata tra tabelle quando si usa il mapping TPT con SQL Server

Problema di rilevamento n. 28532

Comportamento precedente

Quando si esegue il mapping di una gerarchia di ereditarietà usando la strategia TPT, la tabella di base deve contenere una riga per ogni entità salvata, indipendentemente dal tipo effettivo di tale entità. L'eliminazione della riga nella tabella di base deve eliminare righe in tutte le altre tabelle. EF Core configura un'eliminazione a catena per questa operazione.

In EF Core 6.0, un bug nel provider di database di SQL Server significava che queste eliminazioni a catena non venivano create.

Nuovo comportamento

A partire da EF Core 7.0, le eliminazioni a catena vengono ora create per SQL Server esattamente come per gli altri database.

Perché

Le eliminazioni a catena dalla tabella di base alle tabelle secondarie in TPT consentono l'eliminazione di un'entità eliminandone la riga nella tabella di base.

Soluzioni di prevenzione

Nella maggior parte dei casi, questa modifica non dovrebbe causare problemi. Tuttavia, SQL Server è molto restrittivo quando sono configurati più comportamenti a catena tra tabelle. Ciò significa che se esiste una relazione di propagazione esistente tra le tabelle nel mapping TPT, SQL Server potrebbe generare l'errore seguente:

Microsoft.Data.SqlClient.SqlException: istruzione DELETE in conflitto con il vincolo REFERENCE "FK_Blogs_People_OwnerId". Il conflitto si è verificato nel database "Scratch", tabella "dbo. Blogs", colonna 'OwnerId'. L'istruzione è stata interrotta.

Ad esempio, questo modello crea un ciclo di relazioni a catena:

[Table("FeaturedPosts")]
public class FeaturedPost : Post
{
    public int ReferencePostId { get; set; }
    public Post ReferencePost { get; set; } = null!;
}

[Table("Posts")]
public class Post
{
    public int Id { get; set; }
    public string? Title { get; set; }
    public string? Content { get; set; }
}

Uno di questi dovrà essere configurato per non usare le eliminazioni a catena nel server. Ad esempio, per modificare la relazione esplicita:

modelBuilder
    .Entity<FeaturedPost>()
    .HasOne(e => e.ReferencePost)
    .WithMany()
    .OnDelete(DeleteBehavior.ClientCascade);

In alternativa, per modificare la relazione implicita creata per il mapping TPT:

modelBuilder
    .Entity<FeaturedPost>()
    .HasOne<Post>()
    .WithOne()
    .HasForeignKey<FeaturedPost>(e => e.Id)
    .OnDelete(DeleteBehavior.ClientCascade);

Maggiore probabilità di errori occupati/bloccati in SQLite quando non si usa la registrazione write-ahead

Comportamento precedente

Le versioni precedenti del provider SQLite hanno salvato le modifiche tramite una tecnica meno efficiente che è stata in grado di riprovare automaticamente quando la tabella era bloccata/occupata e la registrazione write-ahead (WAL) non era abilitata.

Nuovo comportamento

Per impostazione predefinita, EF Core salva ora le modifiche tramite una tecnica più efficiente, usando la clausola RETURNING. Sfortunatamente, questa tecnica non è in grado di riprovare automaticamente quando è occupato/bloccato. In un'applicazione multithread (ad esempio un'app Web) che non usa la registrazione write-ahead, è comune riscontrare questi errori.

Perché

Per impostazione predefinita, le semplificazioni e i miglioramenti delle prestazioni collegati al nuovo metodo sono sufficientemente importanti da renderli agli utenti. I database creati da EF Core abilitano anche la registrazione write-ahead per impostazione predefinita. Il team di SQLite consiglia anche di abilitare la registrazione write-ahead per impostazione predefinita.

Soluzioni di prevenzione

Se possibile, è consigliabile abilitare la registrazione write-ahead nel database. Se il database è stato creato da ENTITY, questo dovrebbe essere già il caso. In caso contrario, è possibile abilitare la registrazione write-ahead eseguendo il comando seguente.

PRAGMA journal_mode = 'wal';

Se, per qualche motivo, non è possibile abilitare la registrazione write-ahead, è possibile ripristinare il meccanismo precedente per l'intera applicazione inserendo il codice seguente nella configurazione del contesto:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlite(...)
        .ReplaceService<IUpdateSqlGenerator, SqliteLegacyUpdateSqlGenerator>();

Modifiche a basso impatto

Potrebbe essere necessario configurare le proprietà chiave con un operatore di confronto dei valori del provider

Problema di rilevamento n. 27738

Comportamento precedente

In EF Core 6.0, i valori chiave acquisiti direttamente dalle proprietà dei tipi di entità sono stati usati per il confronto dei valori delle chiavi durante il salvataggio delle modifiche. In questo modo si userà qualsiasi operatore di confronto di valori personalizzato configurato in queste proprietà.

Nuovo comportamento

A partire da EF Core 7.0, i valori del database vengono usati per questi confronti. Questo "funziona solo" per la maggior parte dei casi. Tuttavia, se le proprietà utilizzavano un operatore di confronto personalizzato e tale operatore di confronto non può essere applicato ai valori del database, potrebbe essere necessario un "operatore di confronto dei valori del provider", come illustrato di seguito.

Perché

Varie suddivisioni di entità e suddivisione delle tabelle possono comportare il mapping di più proprietà alla stessa colonna di database e viceversa. Questo richiede che i valori vengano confrontati dopo la conversione in valore che verrà usato nel database.

Soluzioni di prevenzione

Configurare un operatore di confronto dei valori del provider. Si consideri ad esempio il caso in cui un oggetto valore viene usato come chiave e l'operatore di confronto per tale chiave usa confronti tra stringhe senza distinzione tra maiuscole e minuscole:

var blogKeyComparer = new ValueComparer<BlogKey>(
    (l, r) => string.Equals(l.Id, r.Id, StringComparison.OrdinalIgnoreCase),
    v => v.Id.ToUpper().GetHashCode(),
    v => v);

var blogKeyConverter = new ValueConverter<BlogKey, string>(
    v => v.Id,
    v => new BlogKey(v));

modelBuilder.Entity<Blog>()
    .Property(e => e.Id).HasConversion(
        blogKeyConverter, blogKeyComparer);

I valori del database (stringhe) non possono usare direttamente l'operatore di confronto definito per BlogKey i tipi. Pertanto, è necessario configurare un operatore di confronto tra stringhe senza distinzione tra maiuscole e minuscole:

var caseInsensitiveComparer = new ValueComparer<string>(
    (l, r) => string.Equals(l, r, StringComparison.OrdinalIgnoreCase),
    v => v.ToUpper().GetHashCode(),
    v => v);

var blogKeyComparer = new ValueComparer<BlogKey>(
    (l, r) => string.Equals(l.Id, r.Id, StringComparison.OrdinalIgnoreCase),
    v => v.Id.ToUpper().GetHashCode(),
    v => v);

var blogKeyConverter = new ValueConverter<BlogKey, string>(
    v => v.Id,
    v => new BlogKey(v));

modelBuilder.Entity<Blog>()
    .Property(e => e.Id).HasConversion(
        blogKeyConverter, blogKeyComparer, caseInsensitiveComparer);

I vincoli Check e altri facet di tabella sono ora configurati nella tabella

Problema di rilevamento n. 28205

Comportamento precedente

In EF Core 6.0, HasCheckConstraint, HasCommente IsMemoryOptimized sono stati chiamati direttamente nel generatore dei tipi di entità. Ad esempio:

modelBuilder
    .Entity<Blog>()
    .HasCheckConstraint("CK_Blog_TooFewBits", "Id > 1023");

modelBuilder
    .Entity<Blog>()
    .HasComment("It's my table, and I'll delete it if I want to.");

modelBuilder
    .Entity<Blog>()
    .IsMemoryOptimized();

Nuovo comportamento

A partire da EF Core 7.0, questi metodi vengono invece chiamati nel generatore di tabelle:

modelBuilder
    .Entity<Blog>()
    .ToTable(b => b.HasCheckConstraint("CK_Blog_TooFewBits", "Id > 1023"));

modelBuilder
    .Entity<Blog>()
    .ToTable(b => b.HasComment("It's my table, and I'll delete it if I want to."));

modelBuilder
    .Entity<Blog>()
    .ToTable(b => b.IsMemoryOptimized());

I metodi esistenti sono stati contrassegnati come Obsolete. Attualmente hanno lo stesso comportamento dei nuovi metodi, ma verranno rimossi in una versione futura.

Perché

Questi facet si applicano solo alle tabelle. Non verranno applicate a viste, funzioni o stored procedure mappate.

Soluzioni di prevenzione

Usare i metodi del generatore di tabelle, come illustrato in precedenza.

Problema di rilevamento n. 28249

Comportamento precedente

In EF Core 6.0, quando viene rilevata una nuova entità da una query di rilevamento o collegandola a DbContext, gli spostamenti verso e dalle entità correlate nello Deleted stato vengono risolte.

Nuovo comportamento

A partire da EF Core 7.0, gli spostamenti da e Deleted verso le entità non vengono risolti.

Perché

Quando un'entità viene contrassegnata come Deleted raramente ha senso associarla a entità non eliminate.

Soluzioni di prevenzione

Eseguire query o collegare entità prima di contrassegnare le entità come Deletedo impostare manualmente le proprietà di navigazione su e dall'entità eliminata.

Problema di rilevamento n. 26502

Comportamento precedente

In EF Core 6.0, l'uso del metodo di estensione Azure Cosmos DB FromSqlRaw quando si usa un provider relazionale o il metodo di estensione relazionale FromSqlRaw quando si usa il provider Azure Cosmos DB potrebbe non riuscire automaticamente. Analogamente, l'uso di metodi relazionali nel provider in memoria è un no-op invisibile all'utente.

Nuovo comportamento

A partire da EF Core 7.0, l'uso di un metodo di estensione progettato per un provider in un provider diverso genererà un'eccezione.

Perché

Il metodo di estensione corretto deve essere usato per funzionare correttamente in tutte le situazioni.

Soluzioni di prevenzione

Usare il metodo di estensione corretto per il provider in uso. Se viene fatto riferimento a più provider, chiamare il metodo di estensione come metodo statico. Ad esempio:

var result = CosmosQueryableExtensions.FromSqlRaw(context.Blogs, "SELECT ...").ToList();

Oppure:

var result = RelationalQueryableExtensions.FromSqlRaw(context.Blogs, "SELECT ...").ToList();

Scaffolding OnConfiguring non più chiamate IsConfigured

Problema di rilevamento n. 4274

Comportamento precedente

In EF Core 6.0 il DbContext tipo sottoposto a scaffolding da un database esistente conteneva una chiamata a IsConfigured. Ad esempio:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
        optionsBuilder.UseNpgsql("MySecretConnectionString");
    }
}

Nuovo comportamento

A partire da EF Core 7.0, la chiamata a IsConfigured non è più inclusa.

Perché

Esistono scenari molto limitati in cui il provider di database è configurato all'interno di DbContext in alcuni casi, ma solo se il contesto non è già configurato. Lasciando qui, invece, OnConfiguring è più probabile che un stringa di connessione contenente informazioni riservate venga lasciato nel codice, nonostante l'avviso in fase di compilazione. Di conseguenza, il codice più sicuro e pulito dalla rimozione di questo è stato considerato utile, soprattutto dato che l'interfaccia --no-onconfiguring della riga di comando (.NET) o -NoOnConfiguring (Console di Visual Studio Gestione pacchetti) può essere usato per impedire lo scaffolding del OnConfiguring metodo e che i modelli personalizzabili esistono per aggiungere di nuovo IsConfigured se è davvero necessario.

Soluzioni di prevenzione

Uno dei seguenti:

  • Usare l'argomento (interfaccia della riga di comando di .NET) o -NoOnConfiguring (Visual Studio Gestione pacchetti Console) durante lo --no-onconfiguring scaffolding da un database esistente.
  • Personalizzare i modelli T4 per aggiungere nuovamente la chiamata a IsConfigured.