Bagikan melalui


Nilai yang Dihasilkan

Kolom database dapat memiliki nilai yang dihasilkan dengan berbagai cara: kolom kunci utama sering kali menambahkan bilangan bulat secara otomatis, kolom lain memiliki nilai default atau komputasi, dll. Halaman ini merinci berbagai pola untuk pembuatan nilai konfigurasi dengan EF Core.

Nilai default

Pada database relasional, kolom dapat dikonfigurasi dengan nilai default; jika baris disisipkan tanpa nilai untuk kolom tersebut, nilai default akan digunakan.

Anda dapat mengonfigurasi nilai default pada properti:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Rating)
        .HasDefaultValue(3);
}

Anda juga dapat menentukan fragmen SQL yang digunakan untuk menghitung nilai default:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Created)
        .HasDefaultValueSql("getdate()");
}

Kolom komputasi

Pada sebagian besar database relasional, kolom dapat dikonfigurasi agar nilainya dihitung dalam database, biasanya dengan ekspresi yang mengacu pada kolom lain:

modelBuilder.Entity<Person>()
    .Property(p => p.DisplayName)
    .HasComputedColumnSql("[LastName] + ', ' + [FirstName]");

Di atas membuat kolom komputasi virtual , yang nilainya dihitung setiap kali diambil dari database. Anda juga dapat menentukan bahwa kolom komputasi disimpan (kadang-kadang disebut bertahan), yang berarti bahwa kolom tersebut dihitung pada setiap pembaruan baris, dan disimpan pada disk bersama kolom reguler:

modelBuilder.Entity<Person>()
    .Property(p => p.NameLength)
    .HasComputedColumnSql("LEN([LastName]) + LEN([FirstName])", stored: true);

Kunci primer

Berdasarkan konvensi, kunci primer non-komposit jenis pendek, int, panjang, atau Guid disiapkan untuk memiliki nilai yang dihasilkan untuk entitas yang disisipkan jika nilai tidak disediakan oleh aplikasi. Penyedia database Anda biasanya mengurus konfigurasi yang diperlukan; misalnya, kunci primer numerik di SQL Server secara otomatis disiapkan menjadi kolom IDENTITY.

Untuk informasi selengkapnya, lihat dokumentasi tentang kunci dan panduan untuk strategi pemetaan pewarisan tertentu.

Mengonfigurasi pembuatan nilai secara eksplisit

Kami melihat di atas bahwa EF Core secara otomatis menyiapkan pembuatan nilai untuk kunci primer - tetapi kami mungkin ingin melakukan hal yang sama untuk properti non-kunci. Anda dapat mengonfigurasi properti apa pun agar nilainya dihasilkan untuk entitas yang disisipkan sebagai berikut:

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

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public DateTime Inserted { get; set; }
}

Demikian pula, properti dapat dikonfigurasi agar nilainya dihasilkan saat menambahkan atau memperbarui:

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

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime LastUpdated { get; set; }
}

Tidak seperti nilai default atau kolom komputasi, kami tidak menentukan bagaimana nilai akan dihasilkan; itu tergantung pada penyedia database yang digunakan. Penyedia database dapat secara otomatis menyiapkan pembuatan nilai untuk beberapa jenis properti, tetapi yang lain mungkin mengharuskan Anda menyiapkan secara manual bagaimana nilai dihasilkan.

Misalnya, di SQL Server, ketika properti GUID dikonfigurasi sebagai kunci utama, penyedia secara otomatis melakukan pembuatan nilai sisi klien, menggunakan algoritma untuk menghasilkan nilai GUID berurutan yang optimal. Namun, menentukan ValueGeneratedOnAdd pada properti DateTime tidak akan berpengaruh (lihat bagian di bawah ini untuk pembuatan nilai DateTime).

Demikian pula, properti byte[] yang dikonfigurasi seperti yang dihasilkan pada tambahkan atau perbarui dan ditandai sebagai token konkurensi disiapkan dengan jenis data rowversion, sehingga nilai secara otomatis dihasilkan dalam database. Namun, menentukan ValueGeneratedOnAdd tidak berpengaruh.

Lihat dokumentasi penyedia Anda untuk teknik pembuatan nilai tertentu yang didukungnya. Dokumentasi pembuatan nilai SQL Server dapat ditemukan di sini.

Pembuatan nilai tanggal/waktu

Permintaan umum adalah memiliki kolom database yang berisi tanggal/waktu saat baris pertama kali disisipkan (nilai yang dihasilkan saat ditambahkan), atau kapan terakhir kali diperbarui (nilai yang dihasilkan pada tambahkan atau perbarui). Karena ada berbagai strategi untuk melakukan ini, penyedia EF Core biasanya tidak menyiapkan pembuatan nilai secara otomatis untuk kolom tanggal/waktu - Anda harus mengonfigurasinya sendiri.

Tanda waktu pembuatan

Mengonfigurasi kolom tanggal/waktu untuk memiliki tanda waktu pembuatan baris biasanya merupakan masalah mengonfigurasi nilai default dengan fungsi SQL yang sesuai. Misalnya, di SQL Server Anda dapat menggunakan hal berikut:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Created)
        .HasDefaultValueSql("getdate()");
}

Pastikan untuk memilih fungsi yang sesuai, karena beberapa mungkin ada (misalnya GETDATE() vs. GETUTCDATE()).

Perbarui tanda waktu

Meskipun kolom komputasi yang disimpan tampak seperti solusi yang baik untuk mengelola tanda waktu terakhir diperbarui, database biasanya tidak mengizinkan menentukan fungsi seperti GETDATE() di kolom komputasi. Sebagai alternatif, Anda dapat menyiapkan pemicu database untuk mencapai efek yang sama:

CREATE TRIGGER [dbo].[Blogs_UPDATE] ON [dbo].[Blogs]
    AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN;

    UPDATE B
    SET LastUpdated = GETDATE()
    FROM dbo.Blogs AS B
    INNER JOIN INSERTED AS I
        ON B.BlogId = I.BlogId
END

Untuk informasi tentang membuat pemicu, lihat dokumentasi tentang menggunakan SQL mentah dalam migrasi.

Mengesampingkan pembuatan nilai

Meskipun properti dikonfigurasi untuk pembuatan nilai, dalam banyak kasus Anda mungkin masih secara eksplisit menentukan nilai untuknya. Apakah ini akan benar-benar berfungsi tergantung pada mekanisme pembuatan nilai tertentu yang telah dikonfigurasi; meskipun Anda dapat menentukan nilai eksplisit alih-alih menggunakan nilai default kolom, hal yang sama tidak dapat dilakukan dengan kolom komputasi.

Untuk mengambil alih pembuatan nilai dengan nilai eksplisit, cukup atur properti ke nilai apa pun yang bukan nilai default CLR untuk jenis properti tersebut (null untuk string, 0 untuk int, Guid.Empty untuk Guid, dll.).

Catatan

Mencoba menyisipkan nilai eksplisit ke dalam IDENTITAS SQL Server gagal secara default; lihat dokumen ini untuk solusinya.

Untuk memberikan nilai eksplisit untuk properti yang telah dikonfigurasi sebagai nilai yang dihasilkan pada penambahan atau pembaruan, Anda juga harus mengonfigurasi properti sebagai berikut:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>().Property(b => b.LastUpdated)
        .ValueGeneratedOnAddOrUpdate()
        .Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Save);
}

Tidak ada pembuatan nilai

Terlepas dari skenario tertentu seperti yang dijelaskan di atas, properti biasanya tidak memiliki pembuatan nilai yang dikonfigurasi; ini berarti bahwa terserah aplikasi untuk selalu menyediakan nilai yang akan disimpan ke database. Nilai ini harus ditetapkan ke entitas baru sebelum ditambahkan ke konteks.

Namun, dalam beberapa kasus Anda mungkin ingin menonaktifkan pembuatan nilai yang telah disiapkan oleh konvensi. Misalnya, kunci primer jenis int biasanya dikonfigurasi secara implisit sebagai value-generated-on-add (misalnya kolom identitas di SQL Server). Anda dapat menonaktifkan ini melalui hal berikut:

public class Blog
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int BlogId { get; set; }

    public string Url { get; set; }
}