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 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 digunakan Encrypt=False
secara default. Ini memungkinkan koneksi pada komputer pengembangan di mana server lokal tidak memiliki sertifikat yang valid.
Perilaku yang baru
SqlClient string koneksi digunakan Encrypt=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:
- 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.
- Jika server memiliki sertifikat, tetapi tidak dipercaya oleh klien, maka
TrustServerCertificate=True
untuk memungkinkan melewati mekanisme kepercayaan normal. - 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
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
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
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
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
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_People_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
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
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.
Navigasi dari entitas baru ke entitas yang dihapus tidak diperbaiki
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 dalamDeleted
status diperbaiki.
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.
Menggunakan FromSqlRaw
dan metode terkait dari penyedia yang salah melemparkan use-the-correct-method
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 = await CosmosQueryableExtensions.FromSqlRaw(context.Blogs, "SELECT ...").ToListAsync();
Atau:
var result = await RelationalQueryableExtensions.FromSqlRaw(context.Blogs, "SELECT ...").ToListAsync();
Perancah OnConfiguring
tidak lagi memanggil IsConfigured
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
.