Bagikan melalui


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.

Petunjuk / Saran

Anda dapat melihat sampel artikel ini di GitHub.

Menggunakan API yang fasih untuk mengonfigurasi model

Anda dapat menggantikan metode OnModelCreating dalam konteks turunan Anda dan menggunakan API Fluent untuk mengonfigurasi model Anda. Ini adalah metode konfigurasi yang paling kuat dan memungkinkan konfigurasi ditentukan tanpa memodifikasi kelas entitas Anda. Konfigurasi API fasih memiliki prioritas tertinggi dan akan mengambil alih 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; }
}

Petunjuk / Saran

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

Konfigurasi pengelompokan

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

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

Kemudian cukup panggil 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 mengimplementasikan IEntityTypeConfiguration dalam perakitan tertentu.

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

Nota

Urutan di mana konfigurasi akan diterapkan tidak terdefinisi, oleh karena itu metode ini hanya boleh digunakan ketika pesanan tidak menjadi masalah.

Menggunakan EntityTypeConfigurationAttribute pada jenis entitas

Alih-alih secara eksplisit memanggil Configure, sebuah EntityTypeConfigurationAttribute dapat 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>();
}

Nota

EntityTypeConfigurationAttribute tipe tidak akan ditemukan secara otomatis dalam perakitan. 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 dapat digantikan oleh konfigurasi Fluent API.

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.

Petunjuk / Saran

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.

Petunjuk / Saran

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. Ketika kita melihat tampilan debug model untuk jenis entitas dengan hubungan ke Post dan Blog, kita dapat melihat bahwa ada dua indeks yang dibuat: satu untuk FK Author dan satu lagi untuk FK BlogId.

  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:

Mengakses tampilan debug pembuat model dari debugger Visual Studio

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));