Haruskah aplikasi ASP.NET MVC langsung menggunakan Entity Framework sebagai model?

22

Saya sedang membangun aplikasi MVC pertama saya di Visual Studio 2013 (MVC 5) dan saya agak tidak jelas tentang cara terbaik untuk mengatur model saya.

Saya telah membuat model kerangka kerja menggunakan kode-pertama dari database yang ada. Insting pertama saya adalah membuat beberapa kelas perantara yang akan menjadi model yang digunakan oleh pandangan dan membuat kelas-kelas itu bekerja dengan kelas kerangka entitas.

Ketika saya sedang menulis kelas perantara, saya menyadari bahwa saya kebanyakan hanya mengimplementasikan kembali banyak hal yang sudah dilakukan oleh kelas EF hanya dengan setter pribadi sesekali atau dilemparkan dari satu tipe data ke tipe data lainnya. Jadi itu sepertinya sia-sia.

Apakah aturan umum untuk langsung menggunakan kelas kerangka kerja entitas sebagai Model untuk aplikasi MVC? Atau adakah manfaat yang saya lewatkan untuk membangun kelas perantara ini?

Mike D.
sumber
Jika Anda menggunakan kode-pertama, maka tidak ada database yang ada, bukan?
Isaac Kleinman
1
Dengan EF 6.1+ Anda dapat menghasilkan model kode-pertama dari database yang ada. Lihat artikel MSDN ini: msdn.microsoft.com/en-au/data/jj200620.aspx
Mike D.

Jawaban:

23

Dalam aplikasi saya, saya selalu memisahkan hal-hal, dengan model yang berbeda untuk database (Entity Framework) dan MVC. Saya telah memisahkan ini ke dalam proyek yang berbeda juga:

  • Example.Entities - berisi entitas saya untuk EF dan konteks DB untuk mengaksesnya.
  • Example.Models - berisi model MVC.
  • Contoh. Web - aplikasi web. Tergantung pada Example.Domain dan Example.Models.

Alih-alih memegang referensi ke objek lain seperti yang dilakukan entitas domain, model MVC menyimpan ID sebagai bilangan bulat.

Ketika permintaan GET untuk halaman masuk, pengontrol MVC melakukan kueri basis data, yang mengembalikan entitas. Saya telah menulis metode "Konverter" yang mengambil entitas domain dan mengubahnya menjadi model MVC. Ada metode lain yang melakukan yang sebaliknya (dari model MVC ke entitas domain). Model kemudian diteruskan ke tampilan, dan dengan demikian ke klien.

Ketika permintaan POST masuk, pengontrol MVC mendapatkan model MVC. Metode konverter mengubahnya menjadi entitas domain. Metode ini juga melakukan validasi apa pun yang tidak dapat dinyatakan sebagai atribut, dan memastikan bahwa jika entitas domain sudah ada, kami memperbaruinya alih-alih mendapatkan yang baru. Metode biasanya terlihat seperti ini:

public class PersonConverter
{
    public MyDatabaseContext _db;

    public PersonEntity Convert(PersonModel source)
    {
         PersonEntity destination = _db.People.Find(source.ID);

         if(destination == null)
             destination = new PersonEntity();

         destination.Name = source.Name;
         destination.Organisation = _db.Organisations.Find(source.OrganisationID);
         //etc

         return destination;
    }

    public PersonModel Convert(PersonEntity source)
    {
         PersonModel destination = new PersonModel()
         {
             Name = source.Name,
             OrganisationID = source.Organisation.ID,
             //etc
         };

         return destination;
    }
}

Dengan menggunakan metode ini saya mengambil duplikasi yang seharusnya terjadi di setiap pengontrol. Penggunaan obat generik dapat mereduplikasi hal-hal lebih jauh.

Melakukan hal-hal seperti ini memberikan banyak manfaat:

  • Anda dapat menyesuaikan model untuk tampilan atau tindakan tertentu. Katakanlah Anda memiliki formulir pendaftaran untuk seseorang yang ketika dikirimkan, membuat banyak entitas yang berbeda (orang, organisasi, alamat). Tanpa model MVC yang terpisah ini akan sangat sulit.
  • Jika saya perlu menyampaikan lebih banyak informasi ke tampilan daripada yang akan tersedia hanya di entitas, atau menggabungkan dua entitas menjadi model tunggal, maka model database berharga saya tidak pernah tersentuh.
  • Jika Anda pernah membuat serial model MVC sebagai JSON atau XML, Anda hanya mendapatkan model segera yang diserialisasi, tidak setiap entitas lain terhubung dengan yang satu ini.
Jack Scott
sumber
Jawaban yang bagus, akan merekomendasikan menggunakan ValueInjector atau sesuatu yang serupa (secara pribadi saya benci automapper) daripada memetakan properti secara manual dari satu kelas ke kelas lainnya.
Rocklan
1
Daripada menambahkan jawaban yang terpisah, saya hanya akan berkomentar di sini bahwa dalam praktik DDD, "konverter" Anda dan model terpisah untuk tampilan akan dianggap sebagai bagian dari Lapisan Layanan Aplikasi. Pada dasarnya, ini memungkinkan Model Domain Anda menjadi serumit yang diperlukan sambil menyembunyikan kerumitan itu dari aplikasi. Ini juga melindungi aplikasi agar tidak diubah karena perubahan dalam model domain. ASL menangani terjemahan.
Michael Brown
Jadi, Anda melakukan panggilan untuk setiap model yang Anda miliki di PersonModel Anda (mis. Objek Organisasi) untuk mendapatkan informasi model itu? Katakanlah Anda memiliki formulir untuk memperbarui orang dan informasi organisasi, apakah Anda memiliki panggilan tambahan ketika Anda memperbarui Organisasi? Saya menggunakan procs tersimpan sehingga saya tidak bisa mengirim semua atribut model dan semua atribut model yang berisi sekaligus?
Luminous
1
Bagaimana Anda menangani pemetaan kembali koleksi? Yang tampaknya jauh lebih rumit di EF6 karena Anda tidak lagi dapat membuat daftar entitas baru dengan pembaruan karena ini hanya menciptakan kembali semuanya ...
Gerard Wilkinson
2
Alih-alih menulis kelas konverter Anda sendiri saya akan merekomendasikan menggunakan perpustakaan Automapper yang telah ditulis untuk mengatasi masalah ini. Telah matang banyak sejak 2014!
BenSmith
6

Saya akan mengatakan itu sangat tergantung pada aplikasi Anda. Apakah hanya melakukan CRUD murni, tanpa logika bisnis? Kemudian saya akan menggunakan model EF secara langsung dalam pandangan saya.

Sebagian besar waktu setidaknya ada beberapa logika bisnis yang terlibat dan kemudian lapisan antara data / model EF dan tampilan mungkin merupakan ide yang bagus. Dalam hal ini mungkin tepat untuk melakukan "CQRS-lite" (lihat di bawah) dan menggunakan model yang berbeda untuk masuk dan keluar dari pengontrol Anda. Sebagian besar waktu model baca jauh lebih "gemuk" daripada model tulis ...

Namun, jika aplikasi mengandung banyak logika bisnis dan / atau kebutuhan untuk skala banyak, saya akan mengimplementasikan setidaknya inti dari itu menggunakan CQRS (Command Query Responsibility Segregation), DDD (Desain Domain Driven Design) dan mungkin Event Sourcing. Kemudian EF dapat digunakan sebagai fasad model baca.

Juga ingat bahwa Anda tidak perlu tetap berpegang pada satu strategi / pola untuk seluruh aplikasi, beberapa area mungkin murni CRUD dan area lain mungkin mengandung banyak logika bisnis ...

jhdrn
sumber