Bagikan melalui


Templat Rekayasa Terbalik Kustom

Catatan

Fitur ini ditambahkan di EF Core 7.

Sementara rekayasa terbalik, Entity Framework Core berusaha untuk membuat perancah kode tujuan umum yang baik yang dapat digunakan dalam berbagai jenis aplikasi dan menggunakan konvensi pengodean umum untuk tampilan yang konsisten dan nuansa yang akrab. Namun, terkadang, kode yang lebih khusus dan gaya pengodean alternatif diinginkan. Artikel ini memperlihatkan cara mengkustomisasi kode perancah menggunakan templat teks T4.

Prasyarat

Artikel ini mengasumsikan Anda terbiasa dengan rekayasa terbalik di EF Core. Jika tidak, silakan tinjau artikel tersebut sebelum melanjutkan.

Menambahkan templat default

Langkah pertama untuk menyesuaikan kode perancah adalah menambahkan templat default ke proyek Anda. Templat default adalah templat yang digunakan secara internal oleh EF Core saat rekayasa terbalik. Mereka menyediakan titik awal bagi Anda untuk mulai menyesuaikan kode perancah.

Mulailah dengan menginstal paket templat EF Core untuk dotnet new:

dotnet new install Microsoft.EntityFrameworkCore.Templates

Sekarang Anda dapat menambahkan templat default ke proyek Anda. Lakukan ini dengan menjalankan perintah berikut dari direktori proyek Anda.

dotnet new ef-templates

Perintah ini menambahkan file berikut ke proyek Anda.

  • CodeTemplates/
    • EFCore/
      • DbContext.t4
      • EntityType.t4

DbContext.t4 Templat digunakan untuk membuat perancah kelas DbContext untuk database, dan EntityType.t4 templat digunakan untuk membuat perancah kelas jenis entitas untuk setiap tabel dan tampilan dalam database.

Tip

Ekstensi .t4 digunakan (bukan .tt) untuk mencegah Visual Studio mengubah templat. Templat akan diubah oleh EF Core sebagai gantinya.

Pengantar T4

Mari kita buka DbContext.t4 templat dan periksa kontennya. File ini adalah templat teks T4. T4 adalah bahasa untuk menghasilkan teks menggunakan .NET. Kode berikut hanya untuk tujuan ilustrasi; ini tidak mewakili isi lengkap file.

Penting

Templat teks T4--terutama yang menghasilkan kode--bisa sulit dibaca tanpa penyorotan sintaks. Jika perlu, cari ekstensi ke editor kode Anda yang mengaktifkan penyorotan sintaks T4.

<#@ template hostSpecific="true" #>
<#@ assembly name="Microsoft.EntityFrameworkCore.Design" #>
<#@ parameter name="NamespaceHint" type="System.String" #>
<#@ import namespace="Microsoft.EntityFrameworkCore" #>
<#
    if (!string.IsNullOrEmpty(NamespaceHint))
    {
#>
namespace <#= NamespaceHint #>;

Beberapa baris pertama yang dimulai dengan <#@ disebut direktif. Mereka memengaruhi bagaimana templat diubah. Tabel berikut ini secara singkat menjelaskan setiap jenis direktif yang digunakan.

Direktif Deskripsi
template Menentukan hostSpecific="true" yang memungkinkan penggunaan Host properti di dalam templat untuk mengakses layanan EF Core.
assembly Menambahkan referensi rakitan yang diperlukan untuk mengkompilasi templat.
parameter Mendeklarasikan parameter yang akan diteruskan oleh EF Core saat mengubah templat.
import Seperti C# menggunakan direktif, membawa namespace ke dalam cakupan untuk kode templat.

Setelah arahan, bagian DbContext.t4 berikutnya disebut blok kontrol. Blok kontrol standar dimulai dengan <# dan diakhir dengan #>. Kode di dalamnya akan dijalankan saat mengubah templat. Untuk daftar properti dan metode yang tersedia di dalam blok kontrol, lihat kelas TextTransformation .

Apa pun di luar blok kontrol akan disalin langsung ke output templat.

Blok kontrol ekspresi dimulai dengan <#=. Kode di dalamnya akan dievaluasi dan hasilnya akan ditambahkan ke output templat. Ini mirip dengan argumen string terinterpolasi C#.

Untuk penjelasan yang lebih rinci dan lengkap tentang sintaks T4, lihat Menulis Templat Teks T4.

Mengkustomisasi jenis entitas

Mari kita telusuri bagaimana rasanya mengkustomisasi templat. Secara default, EF Core menghasilkan kode berikut untuk properti navigasi koleksi.

public virtual ICollection<Album> Albums { get; } = new List<Album>();

Menggunakan List<T> adalah default yang baik untuk sebagian besar aplikasi. Namun, jika Anda menggunakan kerangka kerja berbasis XAML seperti WPF, WinUI, atau .NET MAUI, Anda sering ingin menggunakan ObservableCollection<T> sebagai gantinya untuk mengaktifkan pengikatan data.

EntityType.t4 Buka templat dan temukan di mana templat tersebut menghasilkan List<T>. Terlihat seperti di bawah ini:

    if (navigation.IsCollection)
    {
#>
    public virtual ICollection<<#= targetType #>> <#= navigation.Name #> { get; } = new List<<#= targetType #>>();
<#
    }

Ganti Daftar dengan ObservableCollection.

public virtual ICollection<<#= targetType #>> <#= navigation.Name #> { get; } = new ObservableCollection<<#= targetType #>>();

Kita juga perlu menambahkan arahan using ke kode perancah. Penggunaan ditentukan dalam daftar di dekat bagian atas templat. Tambahkan System.Collections.ObjectModel ke daftar.

var usings = new List<string>
{
    "System",
    "System.Collections.Generic",
    "System.Collections.ObjectModel"
};

Uji perubahan dengan menggunakan perintah rekayasa terbalik. Templat di dalam proyek Anda digunakan secara otomatis oleh perintah.

dotnet ef dbcontext scaffold "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook" Microsoft.EntityFrameworkCore.SqlServer

Jika Anda telah menjalankan perintah sebelumnya, tambahkan --force opsi untuk menimpa file yang ada.

Jika Anda melakukan semuanya dengan benar, properti navigasi koleksi sekarang harus menggunakan ObservableCollection<T>.

public virtual ICollection<Album> Albums { get; } = new ObservableCollection<Album>();

Memperbarui templat

Saat Anda menambahkan templat default ke proyek Anda, templat tersebut akan membuat salinannya berdasarkan versi EF Core tersebut. Karena bug diperbaiki dan fitur ditambahkan dalam versi EF Core berikutnya, templat Anda mungkin kedaluarsa. Anda harus meninjau perubahan yang dibuat dalam templat EF Core dan menggabungkannya ke dalam templat yang disesuaikan.

Salah satu cara untuk meninjau perubahan yang dilakukan pada templat EF Core adalah dengan menggunakan git untuk membandingkannya di antara versi. Perintah berikut akan mengkloning repositori EF Core dan menghasilkan perbedaan file-file ini antara versi 7.0.0 dan 8.0.0.

git clone --no-checkout https://github.com/dotnet/efcore.git
cd efcore
git diff v7.0.0 v8.0.0 -- src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.tt src/EFCore.Design/Scaffolding/Internal/CSharpEntityTypeGenerator.tt

Cara lain untuk meninjau perubahan adalah dengan mengunduh dua versi Microsoft.EntityFrameworkCore.Templates dari NuGet, mengekstrak kontennya (Anda dapat mengubah ekstensi file menjadi .zip), dan membandingkan file tersebut.

Sebelum menambahkan templat default ke proyek baru, ingatlah untuk memperbarui ke paket templat EF Core terbaru.

dotnet new update

Penggunaan tingkat lanjut

Mengabaikan model input

Parameter Model dan EntityType mewakili salah satu kemungkinan cara pemetaan ke database. Anda dapat memilih untuk mengabaikan atau mengubah bagian model. Misalnya, nama navigasi yang kami berikan mungkin tidak ideal, dan Anda dapat menggantinya dengan nama Anda sendiri saat membuat perancah kode. Hal lain seperti nama batasan dan filter indeks hanya digunakan oleh Migrasi dan dapat dihilangkan dengan aman dari model jika Anda tidak berniat menggunakan Migrasi dengan kode perancah. Demikian juga, Anda mungkin ingin menghilangkan urutan atau batasan default jika tidak digunakan oleh aplikasi Anda.

Saat membuat perubahan tingkat lanjut seperti ini, pastikan model yang dihasilkan tetap kompatibel dengan database. Meninjau SQL yang dihasilkan adalah dbContext.Database.GenerateCreateScript() cara yang baik untuk memvalidasi ini.

Kelas konfigurasi entitas

Untuk model besar, metode OnModelCreating dari kelas DbContext dapat menjadi sangat besar. Salah satu cara untuk mengatasinya adalah dengan menggunakan IEntityTypeConfiguration<T> kelas. Lihat Membuat dan mengonfigurasi model untuk informasi selengkapnya tentang kelas-kelas ini.

Untuk membuat perancah kelas-kelas ini, Anda dapat menggunakan templat ketiga yang disebut EntityTypeConfiguration.t4. EntityType.t4 Seperti templat, templat akan digunakan untuk setiap jenis entitas dalam model dan menggunakan EntityType parameter templat.

Perancah jenis file lain

Tujuan utama rekayasa terbalik di EF Core adalah untuk membuat perancah DbContext dan jenis entitas. Namun, tidak ada dalam alat yang mengharuskan Anda untuk benar-benar kode perancah. Misalnya, Anda dapat membuat perancah diagram hubungan entitas menggunakan Mermaid.

<#@ output extension=".md" #>
<#@ assembly name="Microsoft.EntityFrameworkCore" #>
<#@ assembly name="Microsoft.EntityFrameworkCore.Relational" #>
<#@ assembly name="Microsoft.EntityFrameworkCore.Design" #>
<#@ parameter name="Model" type="Microsoft.EntityFrameworkCore.Metadata.IModel" #>
<#@ parameter name="Options" type="Microsoft.EntityFrameworkCore.Scaffolding.ModelCodeGenerationOptions" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="Microsoft.EntityFrameworkCore" #>
# <#= Options.ContextName #>

```mermaid
erDiagram
<#
    foreach (var entityType in Model.GetEntityTypes().Where(e => !e.IsSimpleManyToManyJoinEntityType()))
    {
#>
    <#= entityType.Name #> {
    }
<#
        foreach (var foreignKey in entityType.GetForeignKeys())
        {
#>
    <#= entityType.Name #> <#= foreignKey.IsUnique ? "|" : "}" #>o--<#= foreignKey.IsRequired ? "|" : "o" #>| <#= foreignKey.PrincipalEntityType.Name #> : "<#= foreignKey.GetConstraintName() #>"
<#
        }

        foreach (var skipNavigation in entityType.GetSkipNavigations().Where(n => n.IsLeftNavigation()))
        {
#>
    <#= entityType.Name #> }o--o{ <#= skipNavigation.TargetEntityType.Name #> : <#= skipNavigation.JoinEntityType.Name #>
<#
        }
    }
#>
```