Bagikan melalui


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 = context.Artists
    .Include(e => e.Albums)
    .ToList();

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 OnConfiguringAnda. 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 = context.Blogs
    .Include(e => e.Posts.Where(p => p.Title.Contains("Cheese")))
    .ToList();

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 (misalnya DateDiffWeek, DateFromParts).
  • Terjemahan metode baru pada array byte (misalnya Contains, , LengthSequenceEqual).
  • 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 baru EF.Functions.DataLength .
  • EnableDetailedErrorsmenambahkan 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 dan Addresses akan diacak ke jenis entitas yang disebut Person dan Address. Nama database asli masih dapat dipertahankan.
  • Opsi baru --no-onconfiguring dapat menginstruksikan EF Core untuk mengecualikan OnConfiguring saat membuat perancah model.

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 dan DOTNET_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).