Paradigma berorientasi objek adalah standar untuk perangkat lunak aplikasi. DBMS Relasional - standar untuk menyimpan data dalam perangkat lunak aplikasi. Ya, Anda dapat menulis di Haskell dan menyimpan data secara eksklusif di ClickHouse. Tapi ini tentang arus utama.
ORM memungkinkan Anda untuk
menarik burung hantu di bola dunia untuk berpura-pura tidak ada RDBMS dan data disimpan dalam model objek yang lebih cocok untuk OOP. Masih ada "kecil" masalah seperti itu - abstraksi ini, seperti banyak lainnya, "mengalir". Di mana dalam model objek ada tautan ke objek lain dalam database kunci asing dan id. Pada saat materialisasi entitas, kita dihadapkan pada pilihan:
- Unduh semuanya dan jatuh dari kehabisan memori / batas waktu
- Menunjukkan secara eksplisit dependensi mana yang ingin kita unduh dan yang tidak dan melanggar prinsip jangan tanya
- Memuat dependensi secara implisit berdasarkan permintaan menggunakan Lazy Load dan mendapatkan masalah kinerja di suatu tempat dalam kode yang disebut
Kaki seperti apa yang harus Anda potong: kiri atau kanan?
TLDR Lazy Load tidak begitu buruk jika digunakan hanya untuk menulis dan tidak digunakan saat membaca. Tapi semuanya tidak begitu sederhana dan ada banyak nuansa.Seiring waktu, saya sampai pada kesimpulan bahwa Lazy Load dan / atau ketergantungan entitas pada implementasi ORM adalah kejahatan yang lebih rendah dalam kondisi tertentu.
Dalam subsistem baca, selalu hanya baca DTO
Dalam 90% kasus, masalah dengan Lazy Load muncul tepat saat membaca. Kami mendapatkan daftar entitas, memeriksanya dan mengulang dan mulai memilih semua data yang diperlukan. Kami mendapatkan poros pertanyaan ke database. Dalam hal ini, paling sering satu-satunya hal yang perlu dilakukan adalah mendapatkan data, membuat serial dan mengirimkannya kembali dalam bentuk JSON. Mengapa, kemudian, memuat entitas sama sekali? Tidak perlu menambahkan data ini ke pelacak perubahan UOW, untuk membaca seluruh entitas bersama dengan bidang "ekstra". Sebagai gantinya, Anda selalu dapat menulis
Select
atau
ProjectTo
. Lazy Load tidak diperlukan karena kode C # dari
Select
akan diterjemahkan ke dalam SQL dan dieksekusi di sisi database.
Bagaimana jika logika saya tidak diterjemahkan ke SQL?
Saya merekomendasikan agar
Evaluasi Klien tidak aktif. Pertama, Anda dapat "membantu" dan menambahkan dukungan untuk fungsi yang diperlukan
secara langsung di sub . Bukan pilihan yang buruk ketika datang ke komputasi sederhana, bukan aturan bisnis. Opsi nomor dua: mengekstrak antarmuka dari entitas dan mengimplementasikannya baik di entitas maupun di DTO.
Misalnya, dalam database ada dua bidang: "harga tanpa diskon" dan "harga dengan diskon". Jika bidang "harga diskon" diisi, maka gunakan, jika tidak, maka gunakan bidang dengan harga biasa. Tambahkan satu aturan lagi. Saat membeli 3 produk, Anda hanya membayar untuk 2 yang paling mahal, sementara diskon reguler juga diperhitungkan.
Implementasinya mungkin sebagai berikut:
public interface IHasProductPrice { decimal BasePrice { get; } decimal? SalePrice { get; } } public class Product: IHasProductPrice {
Dalam subsistem tulis, Lazy Load tidak begitu menakutkan
Dalam subsistem tulis, sebaliknya, cukup sering hanya id untuk menulis saja tidak cukup. Semua jenis pemeriksaan sering membuat Anda membaca seluruh entitas, karena paradigma objek melibatkan menggabungkan data dan operasi padanya dalam objek kelas dan invariannya. Jika proyek menggunakan DDD, maka operasi tulis / ubah harus dilakukan melalui akar agregasi, dan oleh karena itu hanya atas satu objek dan dependensinya. Sejumlah besar kueri hanya dapat terjadi saat bekerja dengan koleksi terkait.
Koleksi terkait dalam agregat
Jika ada terlalu banyak data dalam mesin, ini mungkin mengindikasikan masalah desain. Akar agregasi yang khas - keranjang, pesanan, paket. Orang biasanya tidak bekerja dengan data dari ribuan baris, jadi mengunduh seluruh koleksi yang tertaut mungkin bukan yang paling produktif, tetapi bukan operasi yang mematikan. Tetapi jika ada ribuan objek dalam koleksi, ada kemungkinan bahwa tidak ada akar agregasi seperti itu dan pengembang datang dengan itu, karena sangat mudah untuk melakukan ini menggunakan alat improvisasi.
Bagaimana jika masih ada ribuan catatan dalam agregat?
DbContext
ke
konstruktor dan bacalah darinya hanya data yang diperlukan dalam konteks operasi. Ya, melanggar DIP. Entah itu, atau tidak menggunakan unit sama sekali dalam hal ini.
Operasi massal
Mengimpor 10.000 baris file adalah target yang bagus untuk Lazy Load. Di sini, untuk semua masalah subsistem baca, rem ChangeTracker juga ditambahkan. Untuk perekaman massal, Anda harus menggunakan
alat terpisah. Saya lebih suka Batch Extensions, karena sekali lagi Anda dapat melakukannya tanpa membuat entitas. Untuk kasus yang sangat parah, ada prosedur tersimpan lama yang baik dan bahkan
alat DBMS khusus .
Retas seumur hidup
Jika Anda perlu menerapkan operasi massal dan konvensional, Anda harus mulai dengan operasi massal. Operasi normal hanyalah kasus khusus kode massa dalam urutan dengan hanya satu elemen.