Kami saat ini menggunakan Entity Framework sebagai ORM di beberapa aplikasi web, dan sampai sekarang, itu cocok untuk kami karena semua data kami disimpan dalam satu basis data. Kami menggunakan pola repositori, dan memiliki layanan (lapisan domain) yang menggunakannya, dan mengembalikan entitas EF langsung ke pengontrol ASP.NET MVC.
Namun, suatu persyaratan telah muncul untuk menggunakan API pihak ke-3 (melalui layanan web) yang akan memberi kami informasi tambahan yang berkaitan dengan pengguna dalam basis data kami. Di basis data Pengguna lokal kami, kami akan menyimpan ID eksternal yang dapat kami berikan kepada API untuk mendapatkan informasi tambahan. Ada sedikit informasi yang tersedia, tetapi demi kesederhanaan, salah satunya terkait dengan perusahaan pengguna (nama, manajer, kamar, jabatan, lokasi, dll). Informasi ini akan digunakan di berbagai tempat di seluruh aplikasi web kami - bukan hanya digunakan di satu tempat.
Jadi pertanyaan saya adalah, di mana tempat terbaik untuk mengisi dan mengakses informasi ini? Karena digunakan di berbagai tempat, tidaklah masuk akal untuk mengambilnya secara ad-hoc di mana pun kami menggunakan aplikasi web - jadi masuk akal untuk mengembalikan data tambahan ini dari lapisan domain.
Pikiran awal saya adalah hanya untuk membuat kelas model pembungkus yang akan berisi entitas EF (EFUser), dan kelas 'ApiUser' baru yang berisi informasi baru - dan ketika kami mendapatkan pengguna, kami mendapatkan EFUser, dan kemudian mendapatkan tambahan info dari API, dan isi objek ApiUser. Namun, sementara ini tidak masalah untuk mendapatkan pengguna tunggal, itu jatuh ketika mendapatkan beberapa pengguna. Kami tidak dapat menekan API ketika mendapatkan daftar pengguna.
Pikiran kedua saya adalah hanya menambahkan metode tunggal ke entitas EFUser yang mengembalikan ApiUser, dan hanya mengisinya ketika diperlukan. Ini menyelesaikan masalah di atas karena kami hanya mengaksesnya saat kami membutuhkannya.
Atau pemikiran terakhir adalah menyimpan salinan data lokal di dalam basis data kami, dan menyinkronkannya dengan API ketika pengguna masuk. Ini adalah pekerjaan minimal karena ini hanya proses sinkronisasi - dan kami tidak memiliki overhead untuk memukul DB dan API setiap kali kami ingin mendapatkan informasi pengguna. Namun, ini berarti menyimpan data di dua tempat, dan juga berarti data tersebut sudah usang bagi setiap pengguna yang belum masuk untuk sementara waktu.
Adakah yang punya saran atau saran tentang cara terbaik untuk menangani skenario semacam ini?
sumber
it's not really sensible to fetch it on an ad-hoc basis
- Kenapa? Untuk alasan kinerja?Jawaban:
Kasus Anda
Dalam kasus Anda, ketiga opsi tersebut layak. Saya pikir pilihan terbaik mungkin untuk menyinkronkan sumber data Anda di suatu tempat di mana aplikasi asp.net bahkan tidak menyadarinya. Artinya, hindari dua pengambilan di latar depan setiap kali, sinkronkan API dengan db secara diam-diam). Jadi jika itu pilihan yang layak dalam kasus Anda - saya katakan lakukan itu.
Sebuah solusi di mana Anda membuat pengambilan 'sekali' seperti jawaban lain menyarankan sepertinya tidak terlalu layak karena tidak bertahan respon di mana saja dan ASP.NET MVC hanya akan membuat pengambilan untuk setiap permintaan berulang kali.
Saya akan menghindari singleton, saya pikir itu bukan ide yang baik untuk banyak alasan yang biasa.
Jika opsi ketiga tidak dapat dijalankan - satu pilihan adalah malas memuatnya. Yaitu, minta kelas untuk memperluas entitas, dan tekan API sesuai kebutuhan . Itu abstraksi yang sangat berbahaya karena itu bahkan lebih ajaib dan tidak jelas.
Saya kira itu benar-benar bermuara pada beberapa pertanyaan:
Satu atau dua kata tentang pemisahan masalah
Izinkan saya untuk membantah apa yang dikatakan Bobson tentang pemisahan masalah di sini. Pada akhirnya - menempatkan logika dalam entitas seperti itu melanggar pemisahan kekhawatiran sama buruknya.
Memiliki repositori seperti itu melanggar pemisahan kekhawatiran sama buruknya dengan menempatkan logika sentris presentasi di lapisan logika bisnis. Repositori Anda tiba-tiba menyadari hal-hal yang berhubungan dengan presentasi seperti bagaimana Anda menampilkan pengguna di pengontrol MVC asp.net Anda.
Dalam pertanyaan terkait ini saya telah bertanya tentang mengakses entitas langsung dari pengontrol. Izinkan saya mengutip salah satu jawaban di sana:
(Baca sisa jawabannya, ini imo yang sangat bagus).
Adalah naif untuk mengabaikan fakta bahwa ada basis data - ada basis data, dan sekeras apa pun Anda ingin mengabstraksikannya, ia tidak ke mana-mana. Aplikasi Anda akan mengetahui sumber data. Anda tidak akan bisa 'menukar hot itu'. ORM berguna tetapi mereka bocor karena betapa rumitnya masalah yang mereka selesaikan dan karena banyak alasan kinerja (Seperti Pilih n + 1 misalnya).
sumber
Dengan pemisahan kekhawatiran yang tepat , tidak ada yang di atas tingkat Kerangka Entitas / API yang seharusnya menyadari dari mana data berasal. Kecuali panggilan API itu mahal (dalam hal waktu atau pemrosesan), mengakses data yang menggunakannya harus transparan seperti mengakses data dari database.
Maka, cara terbaik untuk mengimplementasikan ini adalah dengan menambahkan properti tambahan ke
EFUser
objek yang malas memuat data API sesuai kebutuhan. Sesuatu seperti ini:Secara eksternal, pertama kali salah satu
CompanyName
atauJobTitle
digunakan akan ada panggilan API tunggal dibuat (dan dengan demikian penundaan kecil), tetapi semua panggilan berikutnya sampai objek dihancurkan akan sama cepat dan mudahnya dengan akses basis data.sumber
Satu ide adalah memodifikasi ApiUser untuk tidak selalu memiliki info tambahan. Sebagai gantinya, Anda meletakkan metode pada ApiUser untuk mengambilnya:
Anda juga dapat sedikit memodifikasi ini untuk menggunakan pemuatan data tambahan yang malas, sehingga Anda tidak perlu mengekstrak UserExtraData dari objek ApiUser:
Dengan cara ini, ketika Anda memiliki daftar, data tambahan tidak akan diambil secara default. Tetapi Anda masih dapat mengaksesnya sambil melintasi daftar!
sumber