Bagikan melalui


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.

Masalah Pelacakan #33732

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 atau MigrateAsync, jika tidak, tambahkan migrasi.
  • 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, atau Guid.NewGuid() digunakan dalam objek yang disediakan untuk 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 HasData().
  • Migrasi terakhir dibuat untuk penyedia yang berbeda dari yang digunakan untuk menerapkan migrasi.
  • 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

Masalah Pelacakan #17578

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

Masalah Pelacakan #35265

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[]?

Masalah Pelacakan #33864

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

Masalah Pelacakan #33852

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

Masalah Pelacakan #33941

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 nullTrue . 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.MemoryMicrosoft.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 mencolok Dampak
Properti diskriminator sekarang dinamai $type alih-alih Discriminator Sangat Penting
Properti id tidak lagi berisi diskriminator secara default Sangat Penting
Properti JSON id dipetakan ke kunci Sangat Penting
Sinkronkan I/O melalui penyedia Azure Cosmos DB tidak lagi didukung Medium
Kueri SQL sekarang harus memproyekan nilai JSON secara langsung Medium
Hasil yang tidak ditentukan sekarang secara otomatis difilter dari hasil kueri Medium
Kueri yang salah diterjemahkan tidak lagi diterjemahkan Medium
HasIndex sekarang melempar alih-alih diabaikan Kurang Penting
IncludeRootDiscriminatorInJsonId diganti namanya menjadi HasRootDiscriminatorInJsonId setelah 9.0.0-rc.2 Kurang Penting

Perubahan berdampak tinggi

Properti diskriminator sekarang dinamai $type alih-alih Discriminator

Masalah Pelacakan #34269

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

Masalah Pelacakan #34179

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 BlogPost 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

Masalah Pelacakan #34179

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

Masalah Pelacakan #32563

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

Masalah Pelacakan #25527

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

Masalah Pelacakan #25527

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

Masalah Pelacakan #34123

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

Masalah Pelacakan #34023

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

Masalah Pelacakan #34717

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.