Yang Baru di EF Core 5.0
Daftar berikut mencakup fitur baru utama di EF Core 5.0. Untuk daftar lengkap masalah dalam rilis, lihat pelacak masalah kami.
Sebagai rilis utama, EF Core 5.0 juga berisi beberapa perubahan yang melanggar, yaitu peningkatan API atau perubahan perilaku yang mungkin berdampak negatif pada aplikasi yang ada.
Banyak-ke-banyak
EF Core 5.0 mendukung hubungan banyak ke banyak tanpa secara eksplisit memetakan tabel gabungan.
Misalnya, pertimbangkan jenis entitas ini:
public class Post
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Tag> Tags { get; set; }
}
public class Tag
{
public int Id { get; set; }
public string Text { get; set; }
public ICollection<Post> Posts { get; set; }
}
EF Core 5.0 mengenali ini sebagai hubungan banyak ke banyak menurut konvensi, dan secara otomatis membuat PostTag
tabel gabungan dalam database. Data dapat dikueri dan diperbarui tanpa secara eksplisit mereferensikan tabel gabungan, sangat menyederhanakan kode. Tabel gabungan masih dapat dikustomisasi dan dikueri secara eksplisit jika diperlukan.
Untuk informasi lebih lanjut, lihat dokumentasi lengkap tentang banyak-ke-banyak.
Memisahkan kueri
Dimulai dengan EF Core 3.0, EF Core selalu menghasilkan satu kueri SQL untuk setiap kueri LINQ. Ini memastikan konsistensi data yang dikembalikan dalam batasan mode transaksi yang digunakan. Namun, ini bisa menjadi sangat lambat ketika kueri menggunakan Include
atau proyeksi untuk mengembalikan beberapa koleksi terkait.
EF Core 5.0 sekarang memungkinkan satu kueri LINQ termasuk koleksi terkait untuk dibagi menjadi beberapa kueri SQL. Ini dapat secara signifikan meningkatkan performa, tetapi dapat mengakibatkan inkonsistensi dalam hasil yang dikembalikan jika data berubah di antara kedua kueri. Transaksi yang dapat diserialisasikan atau rekam jepret dapat digunakan untuk mengurangi hal ini dan mencapai konsistensi dengan kueri terpisah, tetapi itu dapat membawa biaya performa dan perbedaan perilaku lainnya.
Misalnya, pertimbangkan kueri yang menarik dalam dua tingkat koleksi terkait menggunakan Include
:
var artists = await context.Artists
.Include(e => e.Albums)
.ToListAsync();
Secara default, EF Core akan menghasilkan SQL berikut saat menggunakan penyedia SQLite:
SELECT a."Id", a."Name", a0."Id", a0."ArtistId", a0."Title"
FROM "Artists" AS a
LEFT JOIN "Album" AS a0 ON a."Id" = a0."ArtistId"
ORDER BY a."Id", a0."Id"
Dengan kueri terpisah, SQL berikut dihasilkan sebagai gantinya:
SELECT a."Id", a."Name"
FROM "Artists" AS a
ORDER BY a."Id"
SELECT a0."Id", a0."ArtistId", a0."Title", a."Id"
FROM "Artists" AS a
INNER JOIN "Album" AS a0 ON a."Id" = a0."ArtistId"
ORDER BY a."Id"
Kueri terpisah dapat diaktifkan dengan menempatkan operator baru AsSplitQuery
di mana saja dalam kueri LINQ Anda, atau secara global di model OnConfiguring
Anda. Untuk informasi selengkapnya, lihat dokumentasi lengkap tentang kueri terpisah.
Pengelogan sederhana dan diagnostik yang ditingkatkan
EF Core 5.0 memperkenalkan cara sederhana untuk menyiapkan pengelogan melalui metode baru LogTo
. Berikut ini akan menyebabkan pesan pengelogan ditulis ke konsol, termasuk semua SQL yang dihasilkan oleh EF Core:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(Console.WriteLine);
Selain itu, sekarang dimungkinkan untuk memanggil ToQueryString
kueri LINQ apa pun, mengambil SQL yang akan dijalankan kueri:
Console.WriteLine(
ctx.Artists
.Where(a => a.Name == "Pink Floyd")
.ToQueryString());
Akhirnya, berbagai jenis EF Core telah dilengkapi dengan properti yang ditingkatkan DebugView
yang memberikan tampilan terperinci ke dalam internal. Misalnya, ChangeTracker.DebugView dapat dikonsultasikan untuk melihat dengan tepat entitas mana yang sedang dilacak pada saat tertentu.
Untuk informasi lebih lanjut, lihat dokumentasi tentang pengelogan dan penyadapan.
Difilter termasuk
Metode Include
ini sekarang mendukung pemfilteran entitas yang disertakan:
var blogs = await context.Blogs
.Include(e => e.Posts.Where(p => p.Title.Contains("Cheese")))
.ToListAsync();
Kueri ini akan mengembalikan blog bersama dengan setiap posting terkait, tetapi hanya ketika judul posting berisi "Keju".
Untuk informasi selengkapnya, lihat dokumentasi lengkap tentang disertakan yang difilter.
Pemetaan tabel per jenis (TPT)
Secara default, EF Core memetakan hierarki pewarisan jenis .NET ke tabel database tunggal. Ini dikenal sebagai pemetaan table-per-hierarchy (TPH). EF Core 5.0 juga memungkinkan pemetaan setiap jenis .NET dalam hierarki warisan ke tabel database yang berbeda; dikenal sebagai pemetaan table-per-type (TPT).
Misalnya, pertimbangkan model ini dengan hierarki yang dipetakan:
public class Animal
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Cat : Animal
{
public string EducationLevel { get; set; }
}
public class Dog : Animal
{
public string FavoriteToy { get; set; }
}
Dengan TPT, tabel database dibuat untuk setiap jenis dalam hierarki:
CREATE TABLE [Animals] (
[Id] int NOT NULL IDENTITY,
[Name] nvarchar(max) NULL,
CONSTRAINT [PK_Animals] PRIMARY KEY ([Id])
);
CREATE TABLE [Cats] (
[Id] int NOT NULL,
[EducationLevel] nvarchar(max) NULL,
CONSTRAINT [PK_Cats] PRIMARY KEY ([Id]),
CONSTRAINT [FK_Cats_Animals_Id] FOREIGN KEY ([Id]) REFERENCES [Animals] ([Id]) ON DELETE NO ACTION,
);
CREATE TABLE [Dogs] (
[Id] int NOT NULL,
[FavoriteToy] nvarchar(max) NULL,
CONSTRAINT [PK_Dogs] PRIMARY KEY ([Id]),
CONSTRAINT [FK_Dogs_Animals_Id] FOREIGN KEY ([Id]) REFERENCES [Animals] ([Id]) ON DELETE NO ACTION,
);
Untuk informasi lebih lanjut, lihat dokumentasi lengkap tentang TPT.
Pemetaan entitas fleksibel
Jenis entitas biasanya dipetakan ke tabel atau tampilan sehingga EF Core akan menarik kembali konten tabel atau tampilan saat mengkueri jenis tersebut. EF Core 5.0 menambahkan opsi pemetaan tambahan, di mana entitas dapat dipetakan ke kueri SQL (disebut "menentukan kueri"), atau ke fungsi bernilai tabel (TVF):
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Post>().ToSqlQuery(
@"SELECT Id, Name, Category, BlogId FROM posts
UNION ALL
SELECT Id, Name, ""Legacy"", BlogId from legacy_posts");
modelBuilder.Entity<Blog>().ToFunction("BlogsReturningFunction");
}
Fungsi bernilai tabel juga dapat dipetakan ke metode .NET daripada ke DbSet, memungkinkan parameter diteruskan; pemetaan dapat diatur dengan HasDbFunction.
Akhirnya, sekarang dimungkinkan untuk memetakan entitas ke tampilan saat mengkueri (atau ke fungsi atau menentukan kueri), tetapi ke tabel saat memperbarui:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Blog>()
.ToTable("Blogs")
.ToView("BlogsView");
}
Jenis entitas jenis bersama dan tas properti
EF Core 5.0 memungkinkan jenis CLR yang sama untuk dipetakan ke beberapa jenis entitas yang berbeda; jenis tersebut dikenal sebagai jenis entitas jenis bersama. Meskipun jenis CLR apa pun dapat digunakan dengan fitur ini, .NET Dictionary
menawarkan kasus penggunaan yang sangat menarik yang kami sebut "tas properti":
public class ProductsContext : DbContext
{
public DbSet<Dictionary<string, object>> Products => Set<Dictionary<string, object>>("Product");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.SharedTypeEntity<Dictionary<string, object>>("Product", b =>
{
b.IndexerProperty<int>("Id");
b.IndexerProperty<string>("Name").IsRequired();
b.IndexerProperty<decimal>("Price");
});
}
}
Entitas ini kemudian dapat dikueri dan diperbarui sama seperti jenis entitas normal dengan jenis CLR khusus mereka sendiri. Informasi lebih lanjut dapat ditemukan dalam dokumentasi tentang tas properti.
Dependen 1:1 yang diperlukan
Di EF Core 3.1, akhir dependen dari hubungan satu-ke-satu selalu dianggap opsional. Ini paling jelas ketika menggunakan entitas yang dimiliki, karena semua kolom entitas yang dimiliki dibuat sebagai nullable dalam database, bahkan jika mereka dikonfigurasi seperti yang diperlukan dalam model.
Di EF Core 5.0, navigasi ke entitas yang dimiliki dapat dikonfigurasi sebagai dependen yang diperlukan. Contohnya:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>(b =>
{
b.OwnsOne(e => e.HomeAddress,
b =>
{
b.Property(e => e.City).IsRequired();
b.Property(e => e.Postcode).IsRequired();
});
b.Navigation(e => e.HomeAddress).IsRequired();
});
}
DbContextFactory
EF Core 5.0 memperkenalkan AddDbContextFactory
dan AddPooledDbContextFactory
mendaftarkan pabrik untuk membuat instans DbContext dalam kontainer injeksi dependensi aplikasi (D.I.) ; ini dapat berguna ketika kode aplikasi perlu membuat dan membuang instans konteks secara manual.
services.AddDbContextFactory<SomeDbContext>(b =>
b.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test"));
Pada titik ini, layanan aplikasi seperti ASP.NET Pengontrol Core kemudian dapat disuntikkan dengan IDbContextFactory<TContext>
, dan menggunakannya untuk membuat instans konteks:
public class MyController : Controller
{
private readonly IDbContextFactory<SomeDbContext> _contextFactory;
public MyController(IDbContextFactory<SomeDbContext> contextFactory)
=> _contextFactory = contextFactory;
public void DoSomeThing()
{
using (var context = _contextFactory.CreateDbContext())
{
// ...
}
}
}
Untuk informasi selengkapnya, lihat dokumentasi lengkap tentang DbContextFactory.
Pembangunan ulang tabel SQLite
Dibandingkan dengan database lain, SQLite relatif terbatas dalam kemampuan manipulasi skemanya; misalnya, menjatuhkan kolom dari tabel yang ada tidak didukung. EF Core 5.0 bekerja di sekitar batasan ini dengan secara otomatis membuat tabel baru, menyalin data dari tabel lama, menghilangkan tabel lama dan mengganti nama tabel baru. Tabel "membangun kembali" tabel ini, dan memungkinkan operasi migrasi yang sebelumnya tidak didukung diterapkan dengan aman.
Untuk detail tentang operasi migrasi mana yang sekarang didukung melalui pembangunan ulang tabel, lihat halaman dokumentasi ini.
Kolase database
EF Core 5.0 memperkenalkan dukungan untuk menentukan kolatasi teks di tingkat database, kolom, atau kueri. Ini memungkinkan sensitivitas kasus dan aspek tekstual lainnya dikonfigurasi dengan cara yang fleksibel dan tidak membahayakan performa kueri.
Misalnya, berikut ini akan mengonfigurasi Name
kolom agar peka huruf besar/kecil di SQL Server, dan indeks apa pun yang dibuat pada kolom akan berfungsi dengan sesuai:
modelBuilder
.Entity<User>()
.Property(e => e.Name)
.UseCollation("SQL_Latin1_General_CP1_CS_AS");
Untuk informasi lebih lanjut, lihat dokumentasi lengkap tentang kolate dan sensitivitas kasus.
Penghitung acara
EF Core 5.0 mengekspos penghitung peristiwa yang dapat digunakan untuk melacak performa aplikasi Anda dan menemukan berbagai anomali. Cukup lampirkan ke proses yang menjalankan EF dengan alat penghitung dotnet:
> dotnet counters monitor Microsoft.EntityFrameworkCore -p 49496
[Microsoft.EntityFrameworkCore]
Active DbContexts 1
Execution Strategy Operation Failures (Count / 1 sec) 0
Execution Strategy Operation Failures (Total) 0
Optimistic Concurrency Failures (Count / 1 sec) 0
Optimistic Concurrency Failures (Total) 0
Queries (Count / 1 sec) 1,755
Queries (Total) 98,402
Query Cache Hit Rate (%) 100
SaveChanges (Count / 1 sec) 0
SaveChanges (Total) 1
Untuk informasi lebih lanjut, lihat dokumentasi lengkap tentang penghitung peristiwa.
Fitur lainnya
Bangunan model
- API pembuatan model telah diperkenalkan untuk konfigurasi pembanding nilai yang lebih mudah.
- Kolom komputasi sekarang dapat dikonfigurasi sebagai disimpan atau virtual.
- Presisi dan skala sekarang dapat dikonfigurasi melalui API Fasih.
- API pembuatan model baru telah diperkenalkan untuk properti navigasi.
- API pembuatan model baru telah diperkenalkan untuk bidang, mirip dengan properti.
- Jenis .NET PhysicalAddress dan IPAddress sekarang dapat dipetakan ke kolom string database.
- Bidang dukungan sekarang dapat dikonfigurasi melalui atribut baru
[BackingField]
. - Bidang pendukung nullable sekarang diizinkan, memberikan dukungan yang lebih baik untuk default yang dihasilkan penyimpanan di mana default CLR bukan nilai sentinel yang baik (penting
bool
). - Atribut baru
[Index]
dapat digunakan pada jenis entitas untuk menentukan indeks, alih-alih menggunakan API Fasih. - Atribut baru
[Keyless]
dapat digunakan untuk mengonfigurasi jenis entitas karena tidak memiliki kunci. - Secara default, EF Core sekarang menganggap diskriminator sebagai lengkap, yang berarti bahwa ia mengharapkan untuk tidak pernah melihat nilai diskriminator yang tidak dikonfigurasi oleh aplikasi dalam model. Ini memungkinkan beberapa peningkatan performa, dan dapat dinonaktifkan jika kolom diskriminator Anda mungkin menyimpan nilai yang tidak diketahui.
Kueri
- Pengecualian kegagalan terjemahan kueri sekarang berisi alasan yang lebih eksplisit tentang alasan kegagalan, untuk membantu menentukan masalah.
- Kueri tanpa pelacakan sekarang dapat melakukan resolusi identitas, menghindari beberapa instans entitas dikembalikan untuk objek database yang sama.
- Menambahkan dukungan untuk GroupBy dengan agregat kondisional (misalnya
GroupBy(o => o.OrderDate).Select(g => g.Count(i => i.OrderDate != null))
). - Menambahkan dukungan untuk menerjemahkan operator Berbeda melalui elemen grup sebelum agregat.
- Terjemahan dari
Reverse
. - Terjemahan yang disempurnakan untuk
DateTime
SQL Server (misalnyaDateDiffWeek
,DateFromParts
). - Terjemahan metode baru pada array byte (misalnya
Contains
, ,Length
SequenceEqual
). - Terjemahan beberapa operator bitwise tambahan, seperti pelengkap dua.
- Terjemahan lebih dari
FirstOrDefault
string. - Terjemahan kueri yang disempurnakan di sekitar semantik null, menghasilkan kueri yang lebih ketat dan lebih efisien.
- Fungsi yang dipetakan pengguna sekarang dapat dianotasikan untuk mengontrol penyebaran null, sekali lagi menghasilkan kueri yang lebih ketat dan lebih efisien.
- SQL yang berisi blok CASE sekarang jauh lebih ringkas.
- Fungsi SQL Server
DATALENGTH
sekarang dapat dipanggil dalam kueri melalui metode baruEF.Functions.DataLength
. EnableDetailedErrors
menambahkan detail tambahan ke pengecualian.
Menyimpan
- Penyadapan dan peristiwa SaveChanges.
- API telah diperkenalkan untuk mengontrol titik penyimpanan transaksi. Selain itu, EF Core akan secara otomatis membuat titik penyimpanan ketika
SaveChanges
dipanggil dan transaksi sudah berlangsung, dan mengembalikannya jika terjadi kegagalan. - ID transaksi dapat diatur secara eksplisit oleh aplikasi, memungkinkan korelasi peristiwa transaksi yang lebih mudah dalam pengelogan dan di tempat lain.
- Ukuran batch maksimum default untuk SQL Server telah diubah menjadi 42 berdasarkan analisis performa batching.
Migrasi dan perancah
- Tabel sekarang dapat dikecualikan dari migrasi.
- Perintah baru
dotnet ef migrations list
sekarang menunjukkan migrasi mana yang belum diterapkan ke database (Get-Migration
melakukan hal yang sama di Konsol Manajemen Paket). - Skrip migrasi sekarang berisi pernyataan transaksi jika sesuai untuk meningkatkan penanganan kasus di mana aplikasi migrasi gagal.
- Kolom untuk kelas dasar yang tidak dipetakan sekarang diurutkan setelah kolom lain untuk jenis entitas yang dipetakan. Perhatikan bahwa ini hanya berdampak pada tabel yang baru dibuat; urutan kolom untuk tabel yang ada tetap tidak berubah.
- Pembuatan migrasi sekarang dapat diketahui jika migrasi yang dihasilkan idempotoen, dan apakah output akan segera dijalankan atau dihasilkan sebagai skrip.
- Parameter baris perintah baru telah ditambahkan untuk menentukan namespace dalam Migrasi dan perancah.
- Perintah pembaruan database dotnet ef sekarang menerima parameter baru
--connection
untuk menentukan string koneksi. - Perancah database yang ada sekarang mensingkularisasi nama tabel, sehingga tabel bernama
People
danAddresses
akan diacak ke jenis entitas yang disebutPerson
danAddress
. Nama database asli masih dapat dipertahankan. - Opsi baru
--no-onconfiguring
dapat menginstruksikan EF Core untuk mengecualikanOnConfiguring
saat membuat perancah model.
Azure Cosmos DB
- Pengaturan koneksi Azure Cosmos DB telah diperluas.
- Konkurensi optimis sekarang didukung di Azure Cosmos DB melalui penggunaan ETags.
- Metode baru
WithPartitionKey
memungkinkan kunci partisi Azure Cosmos DB disertakan baik dalam model maupun dalam kueri. - Metode
Contains
string ,StartsWith
danEndsWith
sekarang diterjemahkan untuk Azure Cosmos DB. - Operator C#
is
sekarang diterjemahkan di Azure Cosmos DB.
Sqlite
- Kolom komputasi sekarang didukung.
- Mengambil data biner dan string dengan GetBytes, GetChars, dan GetTextReader sekarang lebih efisien dengan menggunakan SqliteBlob dan stream.
- Inisialisasi SqliteConnection sekarang malas.
Lainnya
- Proksi pelacakan perubahan dapat dihasilkan yang secara otomatis mengimplementasikan INotifyPropertyChanging dan INotifyPropertyChanged. Ini menyediakan pendekatan alternatif untuk pelacakan perubahan yang tidak memindai perubahan saat
SaveChanges
dipanggil. - A DbConnection atau string koneksi sekarang dapat diubah pada DbContext yang sudah diinisialisasi.
- Metode baru ChangeTracker.Clear menghapus DbContext dari semua entitas yang dilacak. Ini biasanya tidak diperlukan saat menggunakan praktik terbaik untuk membuat instans konteks baru berumur pendek untuk setiap unit kerja. Namun, jika ada kebutuhan untuk mengatur ulang status instans DbContext, maka menggunakan metode baru
Clear()
lebih efisien dan kuat daripada melepaskan semua entitas secara massal. - Alat baris perintah EF Core sekarang secara otomatis mengonfigurasi
ASPNETCORE_ENVIRONMENT
variabel lingkungan danDOTNET_ENVIRONMENT
ke "Pengembangan". Ini membawa pengalaman saat menggunakan host generik sejalan dengan pengalaman untuk ASP.NET Core selama pengembangan. - Argumen baris perintah kustom dapat dialirkan ke , IDesignTimeDbContextFactory<TContext>memungkinkan aplikasi mengontrol bagaimana konteks dibuat dan diinisialisasi.
- Faktor pengisian indeks sekarang dapat dikonfigurasi di SQL Server.
- Properti baru IsRelational dapat digunakan untuk membedakan saat menggunakan penyedia relasional dan penyedia non-relasi (seperti dalam memori).