Memutus perubahan dalam EF Core 9 (EF9)
Halaman ini mendokuensikan PERUBAHAN API dan perilaku yang berpotensi memutus pembaruan aplikasi yang ada dari EF Core 8 ke EF Core 9. Pastikan untuk meninjau perubahan yang melanggar sebelumnya jika memperbarui dari versi EF Core yang lebih lama:
Kerangka Target
EF Core 9 menargetkan .NET 8. Ini berarti bahwa aplikasi yang ada yang menargetkan .NET 8 dapat terus melakukannya. Aplikasi yang menargetkan versi .NET, .NET Core, dan .NET Framework yang lebih lama perlu menargetkan .NET 8 atau .NET 9 untuk menggunakan EF Core 9.
Ringkasan
Catatan
Jika Anda menggunakan Azure Cosmos DB, silakan lihat bagian terpisah di bawah ini tentang perubahan pemecahan Azure Cosmos DB.
Perubahan mencolok | Dampak |
---|---|
Pengecualian terjadi ketika menerapkan migrasi jika terdapat perubahan model yang belum diproses | Sangat Penting |
Pengecualian dilemparkan saat menerapkan migrasi dalam transaksi eksplisit | Sangat Penting |
Microsoft.EntityFrameworkCore.Design tidak ditemukan saat menggunakan alat EF |
Medium |
EF.Functions.Unhex() sekarang kembali byte[]? |
Kurang Penting |
Aritas argumen nullability SqlFunctionExpression divalidasi | Kurang Penting |
ToString() metode sekarang mengembalikan string kosong untuk null instans |
Kurang Penting |
Dependensi kerangka kerja bersama diperbarui ke 9.0.x | Kurang Penting |
Perubahan berdampak tinggi
Pengecualian terjadi saat menerapkan migrasi jika terdapat perubahan model yang masih tertunda.
Perilaku yang lama
Jika model memiliki perubahan yang tertunda dibandingkan dengan migrasi terakhir, model tersebut tidak diterapkan dengan sisa migrasi saat Migrate
dipanggil.
Perilaku yang baru
Dimulai dengan EF Core 9.0, jika model memiliki perubahan yang tertunda dibandingkan dengan migrasi terakhir, pengecualian dilemparkan ketika dotnet ef database update
, Migrate
atau MigrateAsync
dipanggil:
Model untuk konteks 'DbContext' memiliki perubahan yang tertunda. Tambahkan migrasi baru sebelum memperbarui database. Pengecualian ini dapat ditekan atau dicatat dengan meneruskan ID peristiwa 'RelationalEventId.PendingModelChangesWarning' ke metode 'ConfigureWarnings' di 'DbContext.OnConfiguring' atau 'AddDbContext'.
Mengapa
Lupa menambahkan migrasi baru setelah membuat perubahan model adalah kesalahan umum yang mungkin sulit didiagnosis dalam beberapa kasus. Pengecualian baru memastikan bahwa model aplikasi cocok dengan database setelah migrasi diterapkan.
Mitigasi
Ada beberapa situasi umum ketika pengecualian ini dapat dilemparkan:
- Tidak ada migrasi sama sekali. Ini umum ketika database diperbarui melalui cara lain.
-
Mitigasi: Jika Anda tidak berencana menggunakan migrasi untuk mengelola skema database, hapus panggilan
Migrate
atauMigrateAsync
, jika tidak, tambahkan migrasi.
-
Mitigasi: Jika Anda tidak berencana menggunakan migrasi untuk mengelola skema database, hapus panggilan
- Setidaknya ada satu migrasi, tetapi cuplikan model hilang. Ini umum untuk migrasi yang dibuat secara manual.
- Mitigasi: Menambahkan migrasi baru menggunakan alat EF, ini akan memperbarui rekam jepret model.
- Model ini tidak dimodifikasi oleh pengembang, tetapi dibangun dengan cara yang tidak deterministik menyebabkan EF mendeteksinya sebagai dimodifikasi. Ini umum ketika
new DateTime()
,DateTime.Now
,DateTime.UtcNow
, atauGuid.NewGuid()
digunakan dalam objek yang disediakan untukHasData()
.-
Mitigasi: Tambahkan migrasi baru, periksa kontennya untuk menemukan penyebabnya, dan ganti data dinamis dengan nilai statis yang dikodekan secara permanen dalam model. Migrasi harus dibuat ulang setelah model diperbaiki. Jika data dinamis harus digunakan untuk seeding, pertimbangkan untuk menggunakan pola penyemaian baru alih-alih
HasData()
.
-
Mitigasi: Tambahkan migrasi baru, periksa kontennya untuk menemukan penyebabnya, dan ganti data dinamis dengan nilai statis yang dikodekan secara permanen dalam model. Migrasi harus dibuat ulang setelah model diperbaiki. Jika data dinamis harus digunakan untuk seeding, pertimbangkan untuk menggunakan pola penyemaian baru alih-alih
- Migrasi terakhir dibuat untuk penyedia yang berbeda dari yang digunakan untuk menerapkan migrasi.
- Mitigasi: Ini adalah skenario yang tidak didukung. Peringatan dapat ditekan menggunakan cuplikan kode di bawah ini, tetapi skenario ini kemungkinan akan berhenti berfungsi dalam rilis EF Core di masa mendatang. Solusi yang direkomendasikan adalah untuk menghasilkan serangkaian migrasi terpisah untuk setiap penyedia.
- Migrasi dihasilkan atau dipilih secara dinamis dengan mengganti beberapa layanan EF.
Mitigasi: Peringatan adalah positif palsu dalam kasus ini dan harus diabaikan:
options.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning))
Jika skenario Anda tidak termasuk dalam salah satu kasus di atas dan menambahkan migrasi baru mengakibatkan dibuatnya migrasi yang sama setiap kali atau menghasilkan migrasi kosong, serta pengecualian masih muncul, maka buatlah proyek reproduksi kecil dan bagikan dengan tim EF dalam isu baru.
Pengecualian terjadi saat menerapkan migrasi dalam transaksi eksplisit
Perilaku yang lama
Untuk menerapkan migrasi dengan tangguh, pola berikut umumnya digunakan:
await dbContext.Database.CreateExecutionStrategy().ExecuteAsync(async () =>
{
await using var transaction = await dbContext.Database.BeginTransactionAsync(cancellationToken);
await dbContext.Database.MigrateAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
});
Perilaku yang baru
Dimulai dengan panggilan EF Core 9.0, Migrate
dan MigrateAsync
akan memulai transaksi dan menjalankan perintah menggunakan ExecutionStrategy
dan jika aplikasi Anda menggunakan pola di atas, pengecualian akan dilemparkan:
Kesalahan dihasilkan untuk peringatan 'Microsoft.EntityFrameworkCore.Migrations.MigrationsUserTransactionWarning': Transaksi dimulai sebelum menerapkan migrasi. Ini mencegah kunci database diperoleh dan karenanya database tidak akan dilindungi dari aplikasi migrasi bersamaan. Transaksi dan strategi eksekusi sudah dikelola oleh EF sesuai kebutuhan. Hapus transaksi eksternal. Pengecualian ini dapat ditekan atau dicatat dengan meneruskan ID peristiwa 'RelationalEventId.MigrationsUserTransactionWarning' ke metode 'ConfigureWarnings' di 'DbContext.OnConfiguring' atau 'AddDbContext'.
Mengapa
Menggunakan transaksi eksplisit mencegah kunci database diperoleh dan karenanya database tidak akan dilindungi dari aplikasi migrasi bersamaan, itu juga membatasi EF tentang bagaimana ia dapat mengelola transaksi secara internal.
Mitigasi
Jika hanya ada satu panggilan database di dalam transaksi, hapus transaksi eksternal dan ExecutionStrategy
:
await dbContext.Database.MigrateAsync(cancellationToken);
Jika tidak, jika skenario Anda memerlukan transaksi eksplisit dan Anda memiliki mekanisme lain untuk mencegah aplikasi migrasi bersamaan, abaikan peringatan:
options.ConfigureWarnings(w => w.Ignore(RelationalEventId.MigrationsUserTransactionWarning))
Perubahan dampak sedang
Microsoft.EntityFrameworkCore.Design
tidak ditemukan saat menggunakan alat EF
Perilaku yang lama
Sebelumnya, alat EF memerlukan Microsoft.EntityFrameworkCore.Design
untuk dirujuk dengan cara berikut.
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="*.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Perilaku yang baru
Dimulai dengan .NET SDK 9.0.200 pengecualian dilemparkan ketika alat EF dipanggil:
Tidak dapat memuat file atau assembly 'Microsoft.EntityFrameworkCore.Design, Culture=netral, PublicKeyToken=null'. Sistem tidak dapat menemukan file yang ditentukan
Mengapa
Alat EF mengandalkan perilaku .NET SDK yang tidak terdokumentasi yang menyebabkan aset privat disertakan dalam file .deps.json
yang dihasilkan. Perbaikan ini dilakukan di dalam sdk#45259. Sayangnya, perubahan EF untuk memperhitungkan hal ini tidak memenuhi standar layanan untuk EF 9.0.x, sehingga perbaikan akan dilakukan pada EF 10.
Mitigasi
Sebagai solusi sebelum EF 10 dirilis, Anda dapat menandai referensi perakitan Design
sebagai dapat diterbitkan:
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<Publish>true</Publish>
</PackageReference>
Ini akan menyertakannya dalam file .deps.json
yang dihasilkan, tetapi memiliki efek samping dengan menyalin Microsoft.EntityFrameworkCore.Design.dll
ke folder output dan publikasi.
Perubahan berdampak rendah
EF.Functions.Unhex()
sekarang kembali byte[]?
Perilaku yang lama
Fungsi EF.Functions.Unhex()
sebelumnya diannotasi untuk mengembalikan byte[]
.
Perilaku yang baru
Dimulai dengan EF Core 9.0, Unhex() sekarang dianotasi untuk mengembalikan byte[]?
.
Mengapa
Unhex()
diterjemahkan ke fungsi SQLite unhex
, yang mengembalikan NULL untuk input yang tidak valid. Akibatnya, Unhex()
dikembalikan null
untuk kasus-kasus tersebut, melanggar anotasi.
Mitigasi
Jika Anda yakin bahwa konten teks yang diteruskan untuk Unhex()
mewakili string heksadesimal yang valid, Anda cukup menambahkan operator pengampun null sebagai pernyataan bahwa pemanggilan tidak akan pernah mengembalikan null:
var binaryData = await context.Blogs.Select(b => EF.Functions.Unhex(b.HexString)!).ToListAsync();
Jika tidak, tambahkan pemeriksaan runtime untuk null pada nilai pengembalian Unhex().
Aritas argumen nullability SqlFunctionExpression divalidasi
Perilaku yang lama
Sebelumnya dimungkinkan untuk membuat SqlFunctionExpression
dengan jumlah argumen yang berbeda dan argumen penyebaran nullability.
Perilaku yang baru
Dimulai dengan EF Core 9.0, EF sekarang melemparkan jika jumlah argumen dan argumen propagasi nullability tidak cocok.
Mengapa
Tidak memiliki jumlah argumen yang cocok dan argumen propagasi nullability dapat menyebabkan perilaku yang tidak terduga.
Mitigasi
Pastikan argumentsPropagateNullability
memiliki jumlah elemen yang sama dengan arguments
. Ketika ragu digunakan false
untuk argumen nullability.
ToString()
metode sekarang mengembalikan string kosong untuk null
instans
Perilaku yang lama
Sebelumnya EF mengembalikan hasil yang tidak konsisten untuk ToString()
metode ketika nilai argumen adalah null
. Misalnya ToString()
pada properti dengan bool?
nilai yang dikembalikan null
, tetapi untuk ekspresi non-properti null
yang nilainya bool?
dikembalikan null
True
. Perilaku ini juga tidak konsisten untuk jenis data lainnya, misalnya ToString()
pada null
enum nilai yang mengembalikan string kosong.
Perilaku yang baru
Dimulai dengan EF Core 9.0, ToString()
metode sekarang secara konsisten mengembalikan string kosong dalam semua kasus ketika nilai argumen adalah null
.
Mengapa
Perilaku lama tidak konsisten di berbagai jenis dan situasi data, serta tidak selaras dengan perilaku C#.
Mitigasi
Untuk kembali ke perilaku lama, tulis ulang kueri yang sesuai:
var newBehavior = context.Entity.Select(x => x.NullableBool.ToString());
var oldBehavior = context.Entity.Select(x => x.NullableBool == null ? null : x.NullableBool.ToString());
Dependensi kerangka kerja bersama diperbarui ke 9.0.x
Perilaku yang lama
Aplikasi yang Microsoft.NET.Sdk.Web
menggunakan SDK dan menargetkan net8.0 akan menyelesaikan paket seperti System.Text.Json
, , Microsoft.Extensions.Caching.Memory
Microsoft.Extensions.Configuration.Abstractions
, Microsoft.Extensions.Logging
dan Microsoft.Extensions.DependencyModel
dari kerangka kerja bersama, sehingga rakitan ini biasanya tidak akan disebarkan dengan aplikasi.
Perilaku yang baru
Sementara EF Core 9.0 masih mendukung net8.0 sekarang mereferensikan versi 9.0.x dari System.Text.Json
, Microsoft.Extensions.Caching.Memory
, Microsoft.Extensions.Configuration.Abstractions
, Microsoft.Extensions.Logging
dan Microsoft.Extensions.DependencyModel
. Aplikasi yang menargetkan net8.0 tidak akan dapat memanfaatkan kerangka kerja bersama untuk menghindari penyebaran rakitan ini.
Mengapa
Versi dependensi yang cocok berisi perbaikan keamanan terbaru dan menggunakannya menyederhanakan model layanan untuk EF Core.
Mitigasi
Ubah aplikasi Anda untuk menargetkan net9.0 untuk mendapatkan perilaku sebelumnya.
Perubahan pemecahan Azure Cosmos DB
Pekerjaan ekstensif telah membuat penyedia Azure Cosmos DB lebih baik di 9.0. Perubahan tersebut mencakup sejumlah perubahan yang melanggar berdampak tinggi; jika Anda meningkatkan aplikasi yang ada, silakan baca hal berikut dengan hati-hati.
Perubahan berdampak tinggi
Properti diskriminator sekarang dinamai $type
alih-alih Discriminator
Perilaku yang lama
EF secara otomatis menambahkan properti diskriminator ke dokumen JSON untuk mengidentifikasi jenis entitas yang diwakili dokumen. Di versi EF sebelumnya, properti JSON ini digunakan untuk diberi nama Discriminator
secara default.
Perilaku yang baru
Dimulai dengan EF Core 9.0, properti diskriminator sekarang dipanggil $type
secara default. Jika Anda memiliki dokumen yang ada di Azure Cosmos DB dari versi EF sebelumnya, ini menggunakan penamaan lama Discriminator
, dan setelah memutakhirkan ke EF 9.0, kueri terhadap dokumen tersebut akan gagal.
Mengapa
Praktik JSON yang $type
muncul menggunakan properti dalam skenario di mana jenis dokumen perlu diidentifikasi. Misalnya. System.Text.Json NET juga mendukung polimorfisme, menggunakan $type
sebagai nama properti diskriminator default (dokumen). Untuk menyelaraskan dengan sisa ekosistem dan membuatnya lebih mudah untuk beroperasi dengan alat eksternal, default diubah.
Mitigasi
Mitigasi term mudah adalah hanya mengonfigurasi nama properti diskriminator menjadi Discriminator
, seperti sebelumnya:
modelBuilder.Entity<Session>().HasDiscriminator<string>("Discriminator");
Melakukan ini untuk semua jenis entitas tingkat atas Anda akan membuat EF berulah seperti sebelumnya.
Pada titik ini, jika mau, Anda juga dapat memperbarui semua dokumen Anda untuk menggunakan penamaan baru $type
.
Properti id
sekarang hanya berisi properti kunci EF secara default
Perilaku yang lama
Sebelumnya, EF menyisipkan nilai diskriminator jenis entitas Anda ke id
dalam properti dokumen. Misalnya, jika Anda menyimpan Blog
jenis entitas dengan properti yang Id
berisi 8, properti JSON id
akan berisi Blog|8
.
Perilaku yang baru
Dimulai dengan EF Core 9.0, properti JSON id
tidak lagi berisi nilai diskriminator, dan hanya berisi nilai properti kunci Anda. Untuk contoh di atas, properti JSON id
hanya akan menjadi 8
. Jika Anda memiliki dokumen yang ada di Azure Cosmos DB dari versi EF sebelumnya, ini memiliki nilai diskriminator di properti JSON id
, dan setelah meningkatkan ke EF 9.0, kueri terhadap dokumen tersebut akan gagal.
Mengapa
Karena properti JSON id
harus unik, diskriminator sebelumnya ditambahkan ke dalamnya untuk memungkinkan entitas yang berbeda dengan nilai kunci yang sama ada. Misalnya, ini memungkinkan memiliki dan Blog
Post
dengan properti yang Id
berisi nilai 8 dalam kontainer dan partisi yang sama. Ini selaras lebih baik dengan pola pemodelan data database relasional, di mana setiap jenis entitas dipetakan ke tabelnya sendiri, dan karenanya memiliki ruang kuncinya sendiri.
EF 9.0 umumnya mengubah pemetaan agar lebih selaras dengan praktik dan ekspektasi NoSQL Azure Cosmos DB umum, daripada sesuai dengan harapan pengguna yang berasal dari database relasional. Selain itu, memiliki nilai diskriminator dalam id
properti membuatnya lebih sulit bagi alat dan sistem eksternal untuk berinteraksi dengan dokumen JSON yang dihasilkan EF; sistem eksternal tersebut umumnya tidak menyadari nilai diskriminator EF, yang secara default berasal dari jenis .NET.
Mitigasi
Mitigasi term mudah adalah hanya mengonfigurasi EF untuk menyertakan diskriminator dalam properti JSON id
, seperti sebelumnya. Opsi konfigurasi baru telah diperkenalkan untuk tujuan ini:
modelBuilder.Entity<Session>().HasDiscriminatorInJsonId();
Melakukan ini untuk semua jenis entitas tingkat atas Anda akan membuat EF berulah seperti sebelumnya.
Pada titik ini, jika mau, Anda juga dapat memperbarui semua dokumen Anda untuk menulis ulang properti JSON id
mereka. Perhatikan bahwa ini hanya dimungkinkan jika entitas dari berbagai jenis tidak berbagi nilai id yang sama dalam kontainer yang sama.
Properti id
JSON dipetakan ke kunci
Perilaku yang lama
Sebelumnya, EF membuat properti bayangan yang dipetakan ke properti id
JSON, kecuali salah satu properti dipetakan ke id
secara eksplisit.
Perilaku yang baru
Dimulai dengan EF Core 9, properti kunci akan dipetakan ke properti JSON id
menurut konvensi jika memungkinkan. Ini berarti bahwa properti kunci tidak akan lagi disimpan dalam dokumen dengan nama yang berbeda dengan nilai yang sama, sehingga kode non-EF yang menggunakan dokumen dan mengandalkan properti ini yang ada tidak akan lagi berfungsi dengan benar.
Mengapa
EF 9.0 umumnya mengubah pemetaan agar lebih selaras dengan praktik dan harapan Umum Azure Cosmos DB NoSQL. Dan tidak umum untuk menyimpan nilai kunci dua kali dalam dokumen.
Mitigasi
Jika Anda ingin mempertahankan perilaku EF Core 8, mitigasi term mudah adalah menggunakan opsi konfigurasi baru yang telah diperkenalkan untuk tujuan ini:
modelBuilder.Entity<Session>().HasShadowId();
Melakukan ini untuk semua jenis entitas tingkat atas Anda akan membuat EF berulah seperti sebelumnya. Atau Anda dapat menerapkannya ke semua jenis entitas dalam model dengan satu panggilan:
modelBuilder.HasShadowIds();
Perubahan dampak sedang
Sinkronkan I/O melalui penyedia Azure Cosmos DB tidak lagi didukung
Perilaku yang lama
Sebelumnya, memanggil metode sinkron seperti ToList
atau SaveChanges
akan menyebabkan EF Core memblokir penggunaan secara .GetAwaiter().GetResult()
sinkron saat menjalankan panggilan asinkron terhadap Azure Cosmos DB SDK. Ini dapat mengakibatkan kebuntuan.
Perilaku yang baru
Dimulai dengan EF Core 9.0, EF sekarang melempar secara default saat mencoba menggunakan I/O sinkron. Pesan pengecualian adalah "Azure Cosmos DB tidak mendukung I/O sinkron. Pastikan untuk menggunakan dan menunggu dengan benar hanya metode asinkron saat menggunakan Entity Framework Core untuk mengakses Azure Cosmos DB. Lihat https://aka.ms/ef-cosmos-nosync untuk informasi selengkapnya."
Mengapa
Pemblokiran sinkron pada metode asinkron dapat mengakibatkan kebuntuan, dan Azure Cosmos DB SDK hanya mendukung metode asinkron.
Mitigasi
Dalam EF Core 9.0, kesalahan dapat ditekan dengan:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.ConfigureWarnings(w => w.Ignore(CosmosEventId.SyncNotSupported));
}
Meskipun demikian, aplikasi harus berhenti menggunakan API sinkronisasi dengan Azure Cosmos DB karena ini tidak didukung oleh Azure Cosmos DB SDK. Kemampuan untuk menekan pengecualian akan dihapus dalam rilis EF Core di masa mendatang, setelah itu satu-satunya opsi adalah menggunakan API asinkron.
Kueri SQL sekarang harus memproyekan nilai JSON secara langsung
Perilaku yang lama
Sebelumnya, EF menghasilkan kueri seperti berikut ini:
SELECT c["City"] FROM root c
Kueri tersebut menyebabkan Azure Cosmos DB membungkus setiap hasil dalam objek JSON, sebagai berikut:
[
{
"City": "Berlin"
},
{
"City": "México D.F."
}
]
Perilaku yang baru
Dimulai dengan EF Core 9.0, EF sekarang menambahkan VALUE
pengubah ke kueri sebagai berikut:
SELECT VALUE c["City"] FROM root c
Kueri tersebut menyebabkan Azure Cosmos DB mengembalikan nilai secara langsung, tanpa dibungkus:
[
"Berlin",
"México D.F."
]
Jika aplikasi Anda menggunakan kueri SQL, kueri tersebut kemungkinan rusak setelah meningkatkan ke EF 9.0, karena tidak menyertakan pengubah VALUE
.
Mengapa
Membungkus setiap hasil dalam objek JSON tambahan dapat menyebabkan penurunan performa dalam beberapa skenario, membengkokkan payload hasil JSON, dan bukan cara alami untuk bekerja dengan Azure Cosmos DB.
Mitigasi
Untuk mengurangi, cukup tambahkan pengubah VALUE
ke proyeksi kueri SQL Anda, seperti yang ditunjukkan di atas.
Hasil yang tidak ditentukan sekarang secara otomatis difilter dari hasil kueri
Perilaku yang lama
Sebelumnya, EF menghasilkan kueri seperti berikut ini:
SELECT c["City"] FROM root c
Kueri tersebut menyebabkan Azure Cosmos DB membungkus setiap hasil dalam objek JSON, sebagai berikut:
[
{
"City": "Berlin"
},
{
"City": "México D.F."
}
]
Jika salah satu hasil tidak terdefinisi (misalnya City
properti tidak ada dari dokumen), dokumen kosong dikembalikan, dan EF akan kembali null
untuk hasil tersebut.
Perilaku yang baru
Dimulai dengan EF Core 9.0, EF sekarang menambahkan VALUE
pengubah ke kueri sebagai berikut:
SELECT VALUE c["City"] FROM root c
Kueri tersebut menyebabkan Azure Cosmos DB mengembalikan nilai secara langsung, tanpa dibungkus:
[
"Berlin",
"México D.F."
]
Perilaku Azure Cosmos DB adalah memfilter undefined
nilai secara otomatis dari hasil; ini berarti bahwa jika salah City
satu properti tidak ada dari dokumen, kueri hanya akan mengembalikan satu hasil, bukan dua hasil, dengan satu adalah null
.
Mengapa
Membungkus setiap hasil dalam objek JSON tambahan dapat menyebabkan penurunan performa dalam beberapa skenario, membengkokkan payload hasil JSON, dan bukan cara alami untuk bekerja dengan Azure Cosmos DB.
Mitigasi
Jika mendapatkan null
nilai untuk hasil yang tidak terdefinisi penting untuk aplikasi Anda, coalesce undefined
nilai untuk null
menggunakan operator baru EF.Functions.Coalesce
:
var users = await context.Customer
.Select(c => EF.Functions.CoalesceUndefined(c.City, null))
.ToListAsync();
Kueri yang salah diterjemahkan tidak lagi diterjemahkan
Perilaku yang lama
Sebelumnya, kueri yang diterjemahkan EF seperti berikut ini:
var sessions = await context.Sessions
.Take(5)
.Where(s => s.Name.StartsWith("f"))
.ToListAsync();
Namun, terjemahan SQL untuk kueri ini salah:
SELECT c
FROM root c
WHERE ((c["Discriminator"] = "Session") AND STARTSWITH(c["Name"], "f"))
OFFSET 0 LIMIT @__p_0
Di SQL, WHERE
klausul dievaluasi klausul dan OFFSET
; tetapi dalam kueri LINQ di atas, LIMIT
operator muncul sebelum Take
operator. Akibatnya, kueri tersebut dapat mengembalikan hasil yang salah.
Perilaku yang baru
Dimulai dengan EF Core 9.0, kueri tersebut tidak lagi diterjemahkan, dan pengecualian dilemparkan.
Mengapa
Terjemahan yang salah dapat menyebabkan kerusakan data senyap, yang dapat memperkenalkan bug yang sulit ditemukan di aplikasi Anda. EF selalu lebih suka gagal-cepat dengan membuang di depan daripada mungkin menyebabkan kerusakan data.
Mitigasi
Jika Anda senang dengan perilaku sebelumnya dan ingin menjalankan SQL yang sama, cukup tukar urutan operator LINQ:
var sessions = await context.Sessions
.Where(s => s.Name.StartsWith("f"))
.Take(5)
.ToListAsync();
Sayangnya, Azure Cosmos DB saat ini tidak mendukung OFFSET
klausul dan LIMIT
dalam subkueri SQL, yang merupakan terjemahan yang tepat dari kueri LINQ asli.
Perubahan berdampak rendah
HasIndex
sekarang melempar alih-alih diabaikan
Perilaku yang lama
Sebelumnya, panggilan ke HasIndex diabaikan oleh penyedia EF Cosmos DB.
Perilaku yang baru
Penyedia sekarang melemparkan jika HasIndex ditentukan.
Mengapa
Di Azure Cosmos DB, semua properti diindeks secara default, dan tidak ada pengindeksan yang perlu ditentukan. Meskipun dimungkinkan untuk menentukan kebijakan pengindeksan kustom, ini saat ini tidak didukung oleh EF, dan dapat dilakukan melalui Portal Microsoft Azure tanpa dukungan EF. Karena HasIndex panggilan tidak melakukan apa-apa, mereka tidak lagi diizinkan.
Mitigasi
Hapus panggilan apa pun ke HasIndex.
IncludeRootDiscriminatorInJsonId
diganti namanya menjadi HasRootDiscriminatorInJsonId
setelah 9.0.0-rc.2
Perilaku yang lama
IncludeRootDiscriminatorInJsonId
API diperkenalkan dalam 9.0.0 rc.1.
Perilaku yang baru
Untuk rilis akhir EF Core 9.0, API diganti namanya menjadi HasRootDiscriminatorInJsonId
Mengapa
API terkait lainnya diganti namanya menjadi dimulai dengan Has
bukan Include
, dan yang ini juga diganti namanya untuk konsistensi.
Mitigasi
Jika kode Anda menggunakan IncludeRootDiscriminatorInJsonId
API, cukup ubah menjadi referensi HasRootDiscriminatorInJsonId
sebagai gantinya.