Kami meninjau dua metode berbeda dalam pola repositori generik. Saat ini, ingin memetakan kunci utama ke Id. Tujuannya adalah untuk memetakan ke Generic Repository Interface yang menggunakan Id. Dua solusi disediakan di bawah ini.

Apa implikasi kinerja dari .FindPrimaryKey().Properties. Apakah itu menyebabkan kunci skema pada tabel database dalam mencoba menemukan kunci utama? Apakah itu menyebabkan kelambatan aplikasi?

Bagaimana perbandingannya dalam kinerja vs Metode Kelas Parsial Solusi 2? Opsi apa yang lebih baik dari segi kinerja?

Catatan: Arsitek menuntut penggunaan pola repositori di tempat kerja, jadi terapkan itu. Ketahuilah ada perdebatan seputar masalah ini, tetapi bukan panggilan saya.

Contoh Model Perancah:

namespace Datatest
{
    public partial class Property
    {
        public int Property { get; set; }
        public int DocumentId { get; set; }
        public string Address { get; set; }
    }
}

Contoh Repositori Basis Generik untuk semua tabel:

    public T Get(int id)
    {
        return Table.Find(id);
    }
    public async Task<T> GetAsync(int id)
    {
        return await Table.FindAsync(id);
    }
    public T Single(Expression<Func<T, bool>> predicate)
    {
        return All.Single(predicate);
    }
    public async Task<T> SingleAsync(Expression<Func<T, bool>> predicate)
    {
        return await All.SingleAsync(predicate);
    }
    public T FirstOrDefault(int id)
    {
        return All.FirstOrDefault(CreateEqualityExpressionForId(id));
    }

Solusi 1: FindPrimaryKey()

Repositori Generik di C# Menggunakan Entity Framework

Gunakan EF FindPrimaryKey()

var idName = _context.Model.FindEntityType(typeof(TEntity))
        .FindPrimaryKey().Properties.Single().Name;

Solusi 2: Pemetaan kelas parsial

Net Core: Buat Pemetaan Id Antarmuka Repositori Generik untuk Semua Tabel Pembuatan Kode Otomatis

public partial class Property: IEntity
{
    [NotMapped]
    public int Id { get => PropertyId; set => PropertyId = value; }
}
3
jerrythomas38 7 Agustus 2019, 07:19

1 menjawab

Jawaban Terbaik

Mengenai pendekatan pertama (menggunakan layanan metadata EF Core):

Pertama, EF Core adalah ORM (Object Relational Mapper), yang terpenting disini adalah Mapper.

Kedua, menggunakan apa yang disebut model berbasis kode, yang berarti semua pemetaan disediakan oleh kode dan bukan database sebenarnya (meskipun model dibuat dengan rekayasa balik dari database yang ada).

Dengan kata sederhana, EF Core membuat pada saat runtime struktur data memori yang berisi informasi (metadata) tentang kelas dan properti, dan pemetaannya ke tabel database, kolom, dan hubungan. Semua informasi itu didasarkan pada model kode murni - kelas entitas, konvensi, anotasi data, dan konfigurasi lancar.

Semua perilaku runtime EF Core didasarkan pada model metadata tersebut. EF Core menggunakannya secara internal saat membuat kueri, memetakan hasil kueri ke objek, menautkan properti navigasi, menghasilkan perintah buat/perbarui/hapus dan urutan eksekusinya, perbarui nilai properti FK sementara setelah mendapatkan nilai kunci utama yang dibuat secara otomatis, dll.

Oleh karena itu model metadata dan layanan penemuan (metode) menggunakan struktur data yang dioptimalkan dan (harus) cukup efisien. Dan sekali lagi, tidak ada operasi basis data yang terlibat.

Jadi pendekatan pertama cukup efisien. Dampak kinerja untuk mendapatkan nama properti PK melalui layanan metadata dapat diabaikan dibandingkan dengan pembuatan, eksekusi, dan materialisasi kueri yang sebenarnya.

Juga kinerja pendekatan pertama mirip dengan metode EF Core Find yang Anda gunakan dalam metode lain. Perhatikan bahwa saat memanggil metode Find Anda hanya meneruskan nilai PK dan bukan propertinya. Jadi implementasi metode entah bagaimana harus tahu bagaimana membangun ekspresi Where, bukan? Dan apa yang dilakukannya secara internal sangat mirip dengan cuplikan yang disarankan.


Mengenai pendekatan kedua:

Ini hanya tidak sebanding karena tidak bekerja. Dimungkinkan untuk menggunakan kelas dasar/antarmuka, tetapi hanya jika nama properti sebenarnya dipetakan - seperti semua kelas memiliki properti Id, dan dipetakan ke nama kolom yang berbeda di tabel database menggunakan [Column] anotasi data atau HasColumnName API yang lancar.

Dalam contoh Anda, properti Id adalah [NotMapped] (diabaikan). Yang berarti EF Core tidak dapat memetakan ke kolom tabel. Fakta bahwa Anda memetakan ke properti lain melalui kode (pengambil/penyetel properti) tidak masalah. EF Core bukan kompiler (de), ia tidak dapat melihat kode Anda, oleh karena itu tidak dapat menerjemahkan kueri LINQ menggunakan properti tersebut ke SQL.

Yang di EF Core 2.x mengarah ke evaluasi klien (sangat tidak efisien, membaca seluruh tabel dan menerapkan filter dalam memori), atau pengecualian jika evaluasi klien adalah dikonfigurasi untuk melakukannya. Dan di EF Core 3.0+ itu akan selalu menjadi pengecualian.

Jadi, jika Anda tidak menghapus properti seperti PropertyId dan peta properti Id (yang akan sulit dilakukan dengan model "database first"), "pendekatan" kedua harus dihindari. Dan bahkan jika Anda dapat memetakan properti Id yang sebenarnya, Anda hanya akan menghemat beberapa milidetik. Dan lagi, saat menggunakan Find Anda tidak peduli dengan kinerja, mengapa repot dengan metode yang menggunakan pendekatan yang sama (atau serupa).

4
Ivan Stoev 7 Agustus 2019, 07:30