Membuat dan Mengonfigurasi Model

EF Core menggunakan model metadata untuk menjelaskan bagaimana jenis entitas aplikasi dipetakan ke database yang mendasar. Model ini dibangun menggunakan serangkaian konvensi - heuristik yang mencari pola umum. Model kemudian dapat disesuaikan menggunakan atribut pemetaan (juga dikenal sebagai anotasi data) dan/atau panggilan ke ModelBuilder metode (juga dikenal sebagai API fasih) di OnModelCreating, yang keduanya akan mengambil alih konfigurasi yang dilakukan oleh konvensi.

Sebagian besar konfigurasi dapat diterapkan ke model yang menargetkan penyimpanan data apa pun. Penyedia juga dapat mengaktifkan konfigurasi yang khusus untuk penyimpanan data tertentu dan mereka juga dapat mengabaikan konfigurasi yang tidak didukung atau tidak berlaku. Untuk dokumentasi tentang konfigurasi khusus penyedia, lihat bagian Penyedia database.

Tip

Anda dapat melihat sampel artikel ini di GitHub.

Menggunakan API fasih untuk mengonfigurasi model

Anda dapat mengambil OnModelCreating alih metode dalam konteks turunan Anda dan menggunakan API fasih untuk mengonfigurasi model Anda. Ini adalah metode konfigurasi yang paling canggih dan memungkinkan konfigurasi ditentukan tanpa mengubah kelas entitas. Konfigurasi API fasih memiliki prioritas tertinggi dan akan menggantikan konvensi dan anotasi data. Konfigurasi diterapkan dalam urutan metode dipanggil dan jika ada konflik, panggilan terbaru akan menimpa konfigurasi yang ditentukan sebelumnya.

using Microsoft.EntityFrameworkCore;

namespace EFModeling.EntityProperties.FluentAPI.Required;

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    #region Required
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property(b => b.Url)
            .IsRequired();
    }
    #endregion
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Tip

Untuk menerapkan konfigurasi yang sama ke beberapa objek dalam model, lihat konfigurasi massal.

Konfigurasi pengelompokan

Untuk mengurangi ukuran metode OnModelCreating, semua konfigurasi untuk jenis entitas dapat diekstraksi ke kelas terpisah yang mengimplementasikan IEntityTypeConfiguration<TEntity>.

public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
    public void Configure(EntityTypeBuilder<Blog> builder)
    {
        builder
            .Property(b => b.Url)
            .IsRequired();
    }
}

Kemudian hanya menggunakan metode Configure dari OnModelCreating.

new BlogEntityTypeConfiguration().Configure(modelBuilder.Entity<Blog>());

Menerapkan semua konfigurasi dalam rakitan

Dimungkinkan untuk menerapkan semua konfigurasi yang ditentukan dalam jenis yang menerapkan IEntityTypeConfiguration dalam rakitan tertentu.

modelBuilder.ApplyConfigurationsFromAssembly(typeof(BlogEntityTypeConfiguration).Assembly);

Catatan

Urutan konfigurasi akan diterapkan tidak ditentukan, oleh karena itu metode ini hanya boleh digunakan jika urutannya tidak menjadi persoalan.

Menggunakan EntityTypeConfigurationAttribute pada jenis entitas

Alih-alih secara eksplisit memanggil Configure, dapat EntityTypeConfigurationAttribute ditempatkan pada jenis entitas sehingga EF Core dapat menemukan dan menggunakan konfigurasi yang sesuai. Contohnya:

[EntityTypeConfiguration(typeof(BookConfiguration))]
public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Isbn { get; set; }
}

Atribut ini berarti bahwa EF Core akan menggunakan implementasi yang ditentukan IEntityTypeConfiguration setiap kali Book jenis entitas disertakan dalam model. Jenis entitas disertakan dalam model menggunakan salah satu mekanisme normal. Misalnya, dengan membuat DbSet<TEntity> properti untuk jenis entitas:

public class BooksContext : DbContext
{
    public DbSet<Book> Books { get; set; }

    //...

Atau dengan mendaftarkannya di OnModelCreating:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Book>();
}

Catatan

EntityTypeConfigurationAttribute jenis tidak akan ditemukan secara otomatis dalam rakitan. Jenis entitas harus ditambahkan ke model sebelum atribut akan ditemukan pada jenis entitas tersebut.

Menggunakan anotasi data untuk mengonfigurasi model

Anda juga dapat menerapkan atribut tertentu (dikenal sebagai Anotasi Data) ke kelas dan properti Anda. Anotasi data akan mengambil alih konvensi, tetapi akan ditimpa oleh konfigurasi API Fasih.

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;

namespace EFModeling.EntityProperties.DataAnnotations.Annotations;

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
}

[Table("Blogs")]
public class Blog
{
    public int BlogId { get; set; }

    [Required]
    public string Url { get; set; }
}

Konvensi bawaan

EF Core mencakup banyak konvensi pembuatan model yang diaktifkan secara default. Anda dapat menemukan semuanya dalam daftar kelas yang mengimplementasikan IConvention antarmuka. Namun, daftar itu tidak termasuk konvensi yang diperkenalkan oleh penyedia dan plugin database pihak ketiga.

Aplikasi dapat menghapus atau mengganti salah satu konvensi ini, serta menambahkan konvensi kustom baru yang menerapkan konfigurasi untuk pola yang tidak dikenali oleh EF di luar kotak.

Tip

Kode yang ditunjukkan di bawah ini berasal dari ModelBuildingConventionsSample.cs.

Menghapus konvensi yang sudah ada

Terkadang salah satu konvensi bawaan mungkin tidak sesuai untuk aplikasi Anda, dalam hal ini dapat dihapus.

Tip

Jika model Anda tidak menggunakan atribut pemetaan (alias anotasi data) untuk konfigurasi, maka semua konvensi dengan nama yang berakhirannya AttributeConvention dapat dihapus dengan aman untuk mempercepat pembuatan model.

Contoh: Jangan membuat indeks untuk kolom kunci asing

Biasanya masuk akal untuk membuat indeks untuk kolom kunci asing (FK), dan karenanya ada konvensi bawaan untuk ini: ForeignKeyIndexConvention. Melihat tampilan debug model untuk Post jenis entitas dengan hubungan ke Blog dan Author, kita dapat melihat dua indeks dibuat--satu untuk BlogId FK, dan yang lainnya untuk AuthorId FK.

  EntityType: Post
    Properties:
      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd
      AuthorId (no field, int?) Shadow FK Index
      BlogId (no field, int) Shadow Required FK Index
    Navigations:
      Author (Author) ToPrincipal Author Inverse: Posts
      Blog (Blog) ToPrincipal Blog Inverse: Posts
    Keys:
      Id PK
    Foreign keys:
      Post {'AuthorId'} -> Author {'Id'} ToDependent: Posts ToPrincipal: Author ClientSetNull
      Post {'BlogId'} -> Blog {'Id'} ToDependent: Posts ToPrincipal: Blog Cascade
    Indexes:
      AuthorId
      BlogId

Namun, indeks memiliki overhead, dan mungkin tidak selalu sesuai untuk membuatnya untuk semua kolom FK. Untuk mencapai hal ini, ForeignKeyIndexConvention dapat dihapus saat membangun model:

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Conventions.Remove(typeof(ForeignKeyIndexConvention));
}

Melihat tampilan debug model untuk Post saat ini, kita melihat bahwa indeks pada FK belum dibuat:

  EntityType: Post
    Properties:
      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd
      AuthorId (no field, int?) Shadow FK
      BlogId (no field, int) Shadow Required FK
    Navigations:
      Author (Author) ToPrincipal Author Inverse: Posts
      Blog (Blog) ToPrincipal Blog Inverse: Posts
    Keys:
      Id PK
    Foreign keys:
      Post {'AuthorId'} -> Author {'Id'} ToDependent: Posts ToPrincipal: Author ClientSetNull
      Post {'BlogId'} -> Blog {'Id'} ToDependent: Posts ToPrincipal: Blog Cascade

Jika diinginkan, indeks masih dapat dibuat secara eksplisit untuk kolom kunci asing, baik menggunakan IndexAttribute atau dengan konfigurasi di OnModelCreating.

Tampilan debug

Tampilan debug pembuat model dapat diakses di debugger IDE Anda. Misalnya, dengan Visual Studio:

Accessing the model builder debug view from the Visual Studio debugger

Ini juga dapat diakses langsung dari kode, misalnya untuk mengirim tampilan debug ke konsol:

Console.WriteLine(context.Model.ToDebugString());

Tampilan debug memiliki bentuk pendek dan bentuk panjang. Bentuk panjang juga mencakup semua anotasi, yang dapat berguna jika Anda perlu melihat metadata relasional atau khusus penyedia. Tampilan panjang juga dapat diakses dari kode:

Console.WriteLine(context.Model.ToDebugString(MetadataDebugStringOptions.LongDefault));