Ini bukan praktik yang buruk bagi pengontrol untuk memanggil repositori secara langsung. "Layanan" hanyalah alat lain, jadi gunakan di tempat yang masuk akal.
NikolaiDante berkomentar:
... Pilih pola yang tepat untuk aplikasi yang tepat. Apa yang akan saya katakan adalah Anda harus membuat aplikasi Anda konsisten.
Saya tidak berpikir konsistensi adalah aspek yang paling penting. Kelas "service" dimaksudkan untuk merangkum beberapa logika level yang lebih tinggi sehingga controller tidak perlu mengimplementasikannya. Jika tidak ada "logika tingkat tinggi" yang diperlukan untuk operasi yang diberikan, langsung saja ke repositori.
Untuk mempromosikan Kepedulian Terpisah yang baik dan kemampuan testabilitas, repositori haruslah merupakan ketergantungan yang Anda berikan ke layanan melalui konstruktor:
IFooRepository repository = new FooRepository();
FooService service = new FooService(repository);
service.DoSomething(...);
Jika mencari catatan dalam database membutuhkan beberapa jenis permintaan parameter, sebuah kelas layanan mungkin merupakan tempat yang baik untuk mengambil dalam model tampilan Anda dan membangun kueri yang kemudian dijalankan oleh repositori.
Demikian pula, jika Anda memiliki model tampilan kompleks untuk formulir, kelas layanan dapat merangkum logika membuat, memperbarui, dan menghapus catatan dengan memanggil metode pada Model Domain / Entitas Anda, kemudian bertahan dengan menggunakan repositori.
Pergi ke arah yang berlawanan, jika controller Anda perlu mendapatkan catatan dengan ID-nya, kemudian mendelegasikan ke objek layanan untuk ini seperti memukul paku payung dengan palu godam - itu cara yang lebih dari yang Anda butuhkan.
Saya telah menemukan bahwa pengontrol berada pada posisi terbaik untuk menangani transaksi, atau objek Unit Kerja . Pengontrol atau objek Unit Kerja kemudian akan mendelegasikan ke objek layanan untuk operasi yang kompleks, atau langsung ke repositori untuk operasi sederhana (seperti menemukan catatan dengan Id).
public class ShoppingCartsController : Controller
{
[HttpPost]
public ActionResult Edit(int id, ShoppingCartForm model)
{
// Controller initiates a database session and transaction
using (IStoreContext store = new StoreContext())
{
// Controller goes directly to a repository to find a record by Id
ShoppingCart cart = store.ShoppingCarts.Find(id);
// Controller creates the service, and passes the repository and/or
// the current transaction
ShoppingCartService service = new ShoppingCartService(store.ShoppingCarts);
if (cart == null)
return HttpNotFound();
if (ModelState.IsValid)
{
// Controller delegates to a service object to manipulate the
// Domain Model (ShoppingCart)
service.UpdateShoppingCart(model, cart);
// Controller decides to commit changes
store.SaveChanges();
return RedirectToAction("Index", "Home");
}
else
{
return View(model);
}
}
}
}
Saya pikir campuran layanan dan bekerja dengan repositori secara langsung dapat diterima. Anda dapat lebih lanjut merangkum transaksi dalam objek Unit Kerja jika Anda merasa perlu.
Rincian tanggung jawab seperti ini:
- Pengontrol mengontrol aliran aplikasi
- Mengembalikan "404 Tidak Ditemukan" jika keranjang belanja tidak ada dalam database
- Merender ulang formulir dengan pesan validasi jika validasi gagal
- Menghemat keranjang belanja jika semuanya memeriksa
- Pengontrol mendelegasikan ke kelas layanan untuk mengeksekusi logika bisnis pada Model Domain Anda (atau Entitas). Objek layanan tidak boleh menerapkan logika bisnis! Mereka menjalankan logika bisnis.
- Pengendali dapat mendelegasikan langsung ke repositori untuk operasi sederhana
- Objek layanan mengambil data dalam model tampilan, dan mendelegasikan ke Model Domain untuk menjalankan logika bisnis (mis. Objek layanan memanggil metode pada Model Domain sebelum memanggil metode pada repositori)
- Objek layanan mendelegasikan ke repositori untuk kegigihan data
- Pengendali harus:
- Kelola masa pakai suatu transaksi, atau
- Buat objek Unit Kerja untuk mengelola masa transaksi