Bagikan melalui


Memutus perubahan dalam EF Core 7.0 (EF7)

Halaman ini mendokuensikan PERUBAHAN API dan perilaku yang berpotensi memutus pembaruan aplikasi yang ada dari EF Core 6 ke EF Core 7. Pastikan untuk meninjau perubahan yang melanggar sebelumnya jika memperbarui dari versi EF Core yang lebih lama:

Kerangka Target

EF Core 7.0 menargetkan .NET 6. Ini berarti bahwa aplikasi yang ada yang menargetkan .NET 6 dapat terus melakukannya. Aplikasi yang menargetkan versi .NET, .NET Core, dan .NET Framework yang lebih lama perlu menargetkan .NET 6 atau .NET 7 untuk menggunakan EF Core 7.0.

Ringkasan

Perubahan mencolok Dampak
Encrypt default ke true untuk koneksi SQL Server Sangat Penting
Beberapa peringatan akan kembali melemparkan pengecualian secara default Sangat Penting
Tabel SQL Server dengan pemicu atau kolom komputasi tertentu sekarang memerlukan konfigurasi EF Core khusus Sangat Penting
Tabel SQLite dengan pemicu AFTER dan tabel virtual sekarang memerlukan konfigurasi EF Core khusus Sangat Penting
Dependen hubungan opsional tanpa institusi tidak dihapus secara otomatis Medium
Penghapusan kaskade dikonfigurasi antara tabel saat menggunakan pemetaan TPT dengan SQL Server Medium
Kemungkinan kesalahan sibuk/terkunci yang lebih tinggi pada SQLite saat tidak menggunakan pengelogan write-ahead Medium
Properti kunci mungkin perlu dikonfigurasi dengan perbandingan nilai penyedia Kurang Penting
Periksa batasan dan faset tabel lainnya sekarang dikonfigurasi pada tabel Kurang Penting
Navigasi dari entitas baru ke entitas yang dihapus tidak diperbaiki Kurang Penting
Menggunakan FromSqlRaw dan metode terkait dari penyedia yang salah melempar Kurang Penting
Perancah OnConfiguring tidak lagi memanggil IsConfigured Kurang Penting

Perubahan berdampak tinggi

Encrypt default ke true untuk koneksi SQL Server

Masalah Pelacakan: SqlClient #1210

Penting

Ini adalah perubahan yang parah dalam paket Microsoft.Data.SqlClient . Tidak ada yang dapat dilakukan di EF Core untuk mengembalikan atau mengurangi perubahan ini. Silakan arahkan umpan balik ke Repositori GitHub Microsoft.Data.SqlClient atau hubungi Microsoft Support Professional untuk pertanyaan atau bantuan tambahan.

Perilaku yang lama

SqlClient string koneksi digunakanEncrypt=False secara default. Ini memungkinkan koneksi pada komputer pengembangan di mana server lokal tidak memiliki sertifikat yang valid.

Perilaku yang baru

SqlClient string koneksi digunakanEncrypt=True secara default. Ini berarti bahwa:

  • Server harus dikonfigurasi dengan sertifikat yang valid
  • Klien harus mempercayai sertifikat ini

Jika kondisi ini tidak terpenuhi, maka SqlException akan dilemparkan. Contohnya:

Sambungan berhasil dibuat dengan server, tetapi kemudian terjadi kesalahan selama proses masuk. (penyedia: Penyedia SSL, kesalahan: 0 - Rantai sertifikat dikeluarkan oleh otoritas yang tidak tepercaya.)

Mengapa

Perubahan ini dilakukan untuk memastikan bahwa, secara default, koneksi aman atau aplikasi akan gagal tersambung.

Mitigasi

Ada tiga cara untuk melanjutkan:

  1. Instal sertifikat yang valid di server. Perhatikan bahwa ini adalah proses yang terlibat dan memerlukan mendapatkan sertifikat dan memastikannya ditandatangani oleh otoritas yang dipercaya oleh klien.
  2. Jika server memiliki sertifikat, tetapi tidak dipercaya oleh klien, maka TrustServerCertificate=True untuk memungkinkan melewati mechanim kepercayaan normal.
  3. Tambahkan secara Encrypt=False eksplisit ke string koneksi.

Peringatan

Opsi 2 dan 3 keduanya meninggalkan server dalam status yang berpotensi tidak aman.

Beberapa peringatan melemparkan pengecualian secara default lagi

Masalah Pelacakan #29069

Perilaku yang lama

Di EF Core 6.0, bug di penyedia SQL Server berarti bahwa beberapa peringatan yang dikonfigurasi untuk melempar pengecualian secara default malah dicatat tetapi tidak melemparkan pengecualian. Peringatan ini adalah:

EventId Deskripsi
RelationalEventId.AmbientTransactionWarning Aplikasi mungkin mengharapkan transaksi sekitar digunakan ketika benar-benar diabaikan.
RelationalEventId.IndexPropertiesBothMappedAndNotMappedToTable Indeks menentukan properti yang beberapa dipetakan dan beberapa di antaranya tidak dipetakan ke kolom dalam tabel.
RelationalEventId.IndexPropertiesMappedToNonOverlappingTables Indeks menentukan properti yang memetakan ke kolom pada tabel yang tidak tumpang tindih.
RelationalEventId.ForeignKeyPropertiesMappedToUnrelatedTables Kunci asing menentukan properti yang tidak dipetakan ke tabel terkait.

Perilaku yang baru

Dimulai dengan EF Core 7.0, peringatan ini lagi, secara default, mengakibatkan pengecualian dilemparkan.

Mengapa

Ini adalah masalah yang sangat mungkin menunjukkan kesalahan dalam kode aplikasi yang harus diperbaiki.

Mitigasi

Perbaiki masalah yang mendasar yang menjadi alasan peringatan.

Secara bergantian, tingkat peringatan dapat diubah sehingga hanya dicatat atau ditekan sepenuhnya. Contohnya:

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

Tabel SQL Server dengan pemicu atau kolom komputasi tertentu sekarang memerlukan konfigurasi EF Core khusus

Masalah Pelacakan #27372

Perilaku yang lama

Versi sebelumnya dari penyedia SQL Server menyimpan perubahan melalui teknik yang kurang efisien yang selalu berfungsi.

Perilaku yang baru

Secara default, EF Core sekarang menyimpan perubahan melalui teknik yang jauh lebih efisien; sayangnya, teknik ini tidak didukung di SQL Server jika tabel target memiliki pemicu database, atau jenis kolom komputasi tertentu. Lihat dokumentasi SQL Server untuk detail selengkapnya.

Mengapa

Peningkatan performa yang ditautkan ke metode baru cukup signifikan sehingga penting untuk membawanya kepada pengguna secara default. Pada saat yang sama, kami memperkirakan penggunaan pemicu database atau kolom komputasi yang terpengaruh dalam aplikasi EF Core menjadi cukup rendah sehingga konsekuensi perubahan yang melanggar negatif lebih besar dari perolehan performa.

Mitigasi

Dimulai dengan EF Core 8.0, penggunaan atau tidak klausul "OUTPUT" dapat dikonfigurasi secara eksplisit. Contohnya:

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

Di EF7 atau yang lebih baru, Jika tabel target memiliki pemicu, maka Anda dapat memberi tahu EF Core ini, dan EF akan kembali ke teknik sebelumnya yang kurang efisien. Ini dapat dilakukan dengan mengonfigurasi jenis entitas yang sesuai sebagai berikut:

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

Perhatikan bahwa melakukan ini sebenarnya tidak membuat EF Core membuat atau mengelola pemicu dengan cara apa pun - saat ini hanya memberi tahu EF Core bahwa pemicu ada di tabel. Akibatnya, nama pemicu apa pun dapat digunakan. Menentukan pemicu dapat digunakan untuk mengembalikan perilaku lama meskipun sebenarnya tidak ada pemicu dalam tabel.

Jika sebagian besar atau semua tabel Anda memiliki pemicu, Anda dapat menolak menggunakan teknik yang lebih baru dan efisien untuk semua tabel model Anda dengan menggunakan konvensi pembuatan model berikut:

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

Gunakan konvensi pada Anda DbContext dengan mengambil alih ConfigureConventions:

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

Ini secara efektif memanggil HasTrigger semua tabel model Anda, alih-alih Anda harus melakukannya secara manual untuk setiap tabel.

Tabel SQLite dengan pemicu AFTER dan tabel virtual sekarang memerlukan konfigurasi EF Core khusus

Masalah Pelacakan #29916

Perilaku yang lama

Versi sebelumnya dari penyedia SQLite menyimpan perubahan melalui teknik yang kurang efisien yang selalu berfungsi.

Perilaku yang baru

Secara default, EF Core sekarang menyimpan perubahan melalui teknik yang lebih efisien, menggunakan klausa RETURNING. Sayangnya, teknik ini tidak didukung pada SQLite jika tabel target memiliki database setelah pemicu, adalah virtual, atau jika versi SQLite yang lebih lama sedang digunakan. Lihat dokumentasi SQLite untuk detail selengkapnya.

Mengapa

Penyederhanaan dan peningkatan performa yang ditautkan ke metode baru cukup signifikan sehingga penting untuk membawanya kepada pengguna secara default. Pada saat yang sama, kami memperkirakan penggunaan pemicu database dan tabel virtual dalam aplikasi EF Core menjadi cukup rendah sehingga konsekuensi perubahan melanggar negatif lebih besar dari perolehan performa.

Mitigasi

Dalam EF Core 8.0, UseSqlReturningClause metode ini telah diperkenalkan untuk secara eksplisit kembali ke SQL yang lebih lama dan kurang efisien. Contohnya:

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

Jika Anda masih menggunakan EF Core 7.0, maka dimungkinkan untuk kembali ke mekanisme lama untuk seluruh aplikasi dengan menyisipkan kode berikut dalam konfigurasi konteks Anda:

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

Perubahan dampak sedang

Dependen hubungan opsional tanpa institusi tidak dihapus secara otomatis

Masalah Pelacakan #27217

Perilaku yang lama

Hubungan bersifat opsional jika kunci asingnya dapat diubah ke null. Mengatur kunci asing ke null memungkinkan entitas dependen ada tanpa entitas utama terkait. Hubungan opsional dapat dikonfigurasi untuk menggunakan penghapusan kaskade, meskipun ini bukan default.

Dependen opsional dapat dipotong dari prinsipalnya dengan mengatur kunci asingnya ke null, atau menghapus navigasi ke atau darinya. Di EF Core 6.0, ini akan menyebabkan dependen dihapus ketika hubungan dikonfigurasi untuk penghapusan bertingkat.

Perilaku yang baru

Dimulai dengan EF Core 7.0, dependen tidak lagi dihapus. Perhatikan bahwa jika prinsipal dihapus, maka dependen akan tetap dihapus karena penghapusan bertingkat dikonfigurasi untuk hubungan tersebut.

Mengapa

Dependen dapat ada tanpa hubungan apa pun dengan prinsipal, sehingga memutuskan hubungan tidak boleh menyebabkan entitas dihapus.

Mitigasi

Dependen dapat dihapus secara eksplisit:

context.Remove(blog);

Atau SaveChanges dapat ditimpa atau disadap untuk menghapus dependen tanpa referensi utama. Contohnya:

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

Penghapusan kaskade dikonfigurasi antara tabel saat menggunakan pemetaan TPT dengan SQL Server

Masalah Pelacakan #28532

Perilaku yang lama

Saat memetakan hierarki pewarisan menggunakan strategi TPT, tabel dasar harus berisi baris untuk setiap entitas yang disimpan, terlepas dari jenis aktual entitas tersebut. Menghapus baris dalam tabel dasar harus menghapus baris di semua tabel lainnya. EF Core mengonfigurasi penghapusan kaskade untuk ini.

Di EF Core 6.0, bug di penyedia database SQL Server berarti bahwa penghapusan bertingkat ini tidak dibuat.

Perilaku yang baru

Dimulai dengan EF Core 7.0, penghapusan bertingkat sekarang sedang dibuat untuk SQL Server seperti biasa untuk database lain.

Mengapa

Penghapusan kaskade dari tabel dasar ke sub-tabel di TPT memungkinkan entitas dihapus dengan menghapus barisnya di tabel dasar.

Mitigasi

Dalam kebanyakan kasus, perubahan ini seharusnya tidak menyebabkan masalah apa pun. Namun, SQL Server sangat ketat ketika ada beberapa perilaku kaskade yang dikonfigurasi antar tabel. Ini berarti bahwa jika ada hubungan berkakala yang ada antara tabel dalam pemetaan TPT, maka SQL Server dapat menghasilkan kesalahan berikut:

Microsoft.Data.SqlClient.SqlException: Pernyataan DELETE bertentangan dengan batasan REFERENSI "FK_Blogs_Orang_OwnerId". Konflik terjadi dalam database "Scratch", tabel "dbo. Blogs", kolom 'OwnerId'. Pernyataan ini telah dihapus.

Misalnya, model ini membuat siklus hubungan berkala:

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

Salah satu dari ini perlu dikonfigurasi untuk tidak menggunakan penghapusan kaskade di server. Misalnya, untuk mengubah hubungan eksplisit:

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

Atau untuk mengubah hubungan implisit yang dibuat untuk pemetaan TPT:

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

Kemungkinan kesalahan sibuk/terkunci yang lebih tinggi pada SQLite saat tidak menggunakan pengelogan write-ahead

Perilaku yang lama

Versi sebelumnya dari penyedia SQLite menyimpan perubahan melalui teknik yang kurang efisien yang dapat mencoba kembali secara otomatis ketika tabel terkunci/sibuk dan pengelogan write-ahead (WAL) tidak diaktifkan.

Perilaku yang baru

Secara default, EF Core sekarang menyimpan perubahan melalui teknik yang lebih efisien, menggunakan klausa RETURNING. Sayangnya, teknik ini tidak dapat mencoba kembali secara otomatis ketika sibuk/terkunci. Dalam aplikasi multi-utas (seperti aplikasi web) yang tidak menggunakan pengelogan write-ahead, biasanya mengalami kesalahan ini.

Mengapa

Penyederhanaan dan peningkatan performa yang ditautkan ke metode baru cukup signifikan sehingga penting untuk membawanya kepada pengguna secara default. Database yang dibuat oleh EF Core juga mengaktifkan pengelogan write-ahead secara default. Tim SQLite juga merekomendasikan untuk mengaktifkan pengelogan write-ahead secara default.

Mitigasi

Jika memungkinkan, Anda harus mengaktifkan pengelogan write-ahead pada database Anda. Jika database Anda dibuat oleh EF, ini seharusnya sudah terjadi. Jika tidak, Anda dapat mengaktifkan pengelogan write-ahead dengan menjalankan perintah berikut.

PRAGMA journal_mode = 'wal';

Jika, karena alasan tertentu, Anda tidak dapat mengaktifkan pengelogan write-ahead, dimungkinkan untuk kembali ke mekanisme lama untuk seluruh aplikasi dengan menyisipkan kode berikut dalam konfigurasi konteks Anda:

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

Perubahan berdampak rendah

Properti kunci mungkin perlu dikonfigurasi dengan perbandingan nilai penyedia

Masalah Pelacakan #27738

Perilaku yang lama

Di EF Core 6.0, nilai kunci yang diambil langsung dari properti jenis entitas digunakan untuk perbandingan nilai kunci saat menyimpan perubahan. Ini akan menggunakan perbandingan nilai kustom apa pun yang dikonfigurasi pada properti ini.

Perilaku yang baru

Dimulai dengan EF Core 7.0, nilai database digunakan untuk perbandingan ini. Ini "hanya berfungsi" untuk sebagian besar kasus. Namun, jika properti menggunakan pembanding kustom, dan perbandingan tersebut tidak dapat diterapkan ke nilai database, maka "perbandingan nilai penyedia" mungkin diperlukan, seperti yang ditunjukkan di bawah ini.

Mengapa

Berbagai pemisahan entitas dan pemisahan tabel dapat menghasilkan beberapa properti yang dipetakan ke kolom database yang sama, dan sebaliknya. Ini mengharuskan nilai dibandingkan setelah konversi ke nilai yang akan digunakan dalam database.

Mitigasi

Mengonfigurasi perbandingan nilai penyedia. Misalnya, pertimbangkan kasus di mana objek nilai digunakan sebagai kunci, dan pembanding untuk kunci tersebut menggunakan perbandingan string yang tidak peka huruf besar/kecil:

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);

Nilai database (string) tidak dapat langsung menggunakan pembanding yang ditentukan untuk BlogKey jenis. Oleh karena itu, perbandingan penyedia untuk perbandingan string yang tidak peka huruf besar/kecil harus dikonfigurasi:

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);

Periksa batasan dan faset tabel lainnya sekarang dikonfigurasi pada tabel

Masalah Pelacakan #28205

Perilaku yang lama

Di EF Core 6.0, HasCheckConstraint, HasComment, dan IsMemoryOptimized dipanggil langsung pada penyusun jenis entitas. Contohnya:

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();

Perilaku yang baru

Dimulai dengan EF Core 7.0, metode ini malah dipanggil pada penyusun tabel:

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());

Metode yang ada telah ditandai sebagai Obsolete. Mereka saat ini memiliki perilaku yang sama dengan metode baru, tetapi akan dihapus dalam rilis mendatang.

Mengapa

Faset ini hanya berlaku untuk tabel. Mereka tidak akan diterapkan ke tampilan, fungsi, atau prosedur tersimpan yang dipetakan.

Mitigasi

Gunakan metode penyusun tabel, seperti yang ditunjukkan di atas.

Masalah Pelacakan #28249

Perilaku yang lama

Di EF Core 6.0, ketika entitas baru dilacak baik dari kueri pelacakan atau dengan melampirkannya ke DbContext, lalu navigasi ke dan dari entitas terkait dalamDeletedstatusdiperbaiki.

Perilaku yang baru

Dimulai dengan EF Core 7.0, navigasi ke dan dari Deleted entitas tidak diperbaiki.

Mengapa

Setelah entitas ditandai karena Deleted jarang masuk akal untuk mengaitkannya dengan entitas yang tidak dihapus.

Mitigasi

Kueri atau lampirkan entitas sebelum menandai entitas sebagai Deleted, atau mengatur properti navigasi secara manual ke dan dari entitas yang dihapus.

Masalah Pelacakan #26502

Perilaku yang lama

Di EF Core 6.0, menggunakan metode ekstensi Azure Cosmos DB FromSqlRaw saat menggunakan penyedia relasional, atau metode ekstensi relasional FromSqlRaw saat menggunakan penyedia Azure Cosmos DB dapat gagal secara diam-diam. Demikian juga, menggunakan metode relasional pada penyedia dalam memori adalah no-op senyap.

Perilaku yang baru

Dimulai dengan EF Core 7.0, menggunakan metode ekstensi yang dirancang untuk satu penyedia pada penyedia yang berbeda akan melemparkan pengecualian.

Mengapa

Metode ekstensi yang benar harus digunakan agar berfungsi dengan benar dalam semua situasi.

Mitigasi

Gunakan metode ekstensi yang benar untuk penyedia yang digunakan. Jika beberapa penyedia dirujuk, panggil metode ekstensi sebagai metode statis. Contohnya:

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

Atau:

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

Perancah OnConfiguring tidak lagi memanggil IsConfigured

Masalah Pelacakan #4274

Perilaku yang lama

Di EF Core 6.0, DbContext jenis yang di-scaffold dari database yang ada berisi panggilan ke IsConfigured. Contohnya:

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

Perilaku yang baru

Dimulai dengan EF Core 7.0, panggilan ke IsConfigured tidak lagi disertakan.

Mengapa

Ada skenario yang sangat terbatas di mana penyedia database dikonfigurasi di dalam DbContext Anda dalam beberapa kasus, tetapi hanya jika konteks belum dikonfigurasi. Sebaliknya, meninggalkan OnConfiguring sini membuatnya lebih mungkin bahwa string koneksi yang berisi informasi sensitif dibiarkan dalam kode, meskipun ada peringatan waktu kompilasi. Dengan demikian, kode ekstra aman dan lebih bersih dari menghapus ini dianggap berharga, terutama mengingat bahwa --no-onconfiguring bendera (.NET CLI) atau -NoOnConfiguring (Konsol Manajer Paket Visual Studio) dapat digunakan untuk mencegah perancah OnConfiguring metode, dan bahwa templat yang dapat disesuaikan ada untuk ditambahkan kembali IsConfigured jika benar-benar diperlukan.

Mitigasi

Yaitu:

  • --no-onconfiguring Gunakan argumen (.NET CLI) atau -NoOnConfiguring (Visual Studio Package Manager Console) saat perancah dari database yang sudah ada.
  • Kustomisasi templat T4 untuk menambahkan kembali panggilan ke IsConfigured.