Kerangka Entitas dengan sistem besar - cara membagi model?


50

Saya bekerja dengan database SQL Server dengan 1000 tabel, beberapa ratus tampilan, dan beberapa ribu prosedur tersimpan. Kami sedang mencari untuk mulai menggunakan Entity Framework untuk proyek-proyek baru kami, dan kami sedang mengerjakan strategi kami untuk melakukannya. Hal yang saya tutup adalah bagaimana cara terbaik untuk membagi tabel menjadi model yang berbeda (EDMX atau DbContext jika kita pergi kode dulu). Saya dapat memikirkan beberapa strategi langsung:

  • Dibagi berdasarkan skema
    Kami memiliki tabel kami yang dibagi menjadi mungkin selusin skema. Kita bisa melakukan satu model per skema. Ini tidak sempurna, karena dbo masih menjadi sangat besar, dengan 500+ tabel / tampilan. Masalah lain adalah bahwa unit kerja tertentu pada akhirnya harus melakukan transaksi yang menjangkau beberapa model, yang menambah kompleksitas, meskipun saya berasumsi EF membuat ini cukup mudah.
  • Pisahkan dengan niat
    Daripada mengkhawatirkan skema, pisahkan model dengan niat. Jadi kita akan memiliki model yang berbeda untuk setiap aplikasi, atau proyek, atau modul, atau layar, tergantung pada seberapa granular yang ingin kita dapatkan. Masalah yang saya lihat dengan ini adalah bahwa ada tabel tertentu yang mau tidak mau harus digunakan dalam setiap kasus, seperti Pengguna atau AuditHistory. Apakah kita menambahkan itu ke setiap model (saya pikir ini melanggar KERING), atau apakah mereka dalam model terpisah yang digunakan oleh setiap proyek?
  • Jangan berpisah sama sekali - satu model raksasa
    Ini jelas sederhana dari sudut pandang pengembangan tetapi dari penelitian dan intuisi saya ini sepertinya bisa tampil sangat, baik pada waktu desain, waktu kompilasi, dan mungkin waktu yang berjalan.

Apa praktik terbaik untuk menggunakan EF terhadap basis data yang begitu besar? Khususnya strategi apa yang digunakan orang dalam merancang model terhadap volume objek DB ini? Apakah ada opsi yang menurut saya tidak lebih baik daripada yang saya miliki di atas?

Juga, apakah ini masalah di ORM lain seperti NHibernate? Jika ya, apakah mereka menghasilkan solusi yang lebih baik daripada EF?


"Harus melakukan transaksi yang menjangkau beberapa model, yang menambah kompleksitas" Hanya perlu diketahui di sini bahwa Anda harus mengaktifkan Koordinator Transaksi Terdistribusi Microsoft. Setelah Anda menjalankan dan menjalankannya, haruslah sederhana untuk mencapai apa yang Anda bicarakan.
Tjaart

@ David terima kasih. Saya telah menggunakan MS DTC sebelum dan sementara itu cukup sederhana, ia menambah kompleksitas di luar DB txn sederhana jadi saya ingin menghindarinya kapanpun memungkinkan.
RationalGeek

2
4 tahun kemudian, apa yang Anda putuskan dan apa yang sekarang akan Anda rekomendasikan?
Rory

Jawaban:


31

Secara pribadi, saya sudah mencoba membuat satu skema besar untuk semua entitas saya pada proyek yang cukup kompleks tetapi kecil (~ 300 tabel). Kami memiliki basis data yang sangat normal (normalisasi formulir ke-5 (saya katakan dengan longgar)) dengan banyak hubungan "banyak ke banyak" dan penegakan integritas referensial ekstrem.

Kami juga menggunakan strategi "satu contoh per permintaan" yang saya tidak yakin membantu.

Ketika melakukan daftar sederhana, cukup datar "didefinisikan secara eksplisit", mencari dan menyimpan kinerja secara umum dapat diterima. Tetapi ketika kami mulai menggali hubungan yang dalam, kinerja itu tampaknya mengalami penurunan drastis. Dibandingkan dengan proc yang disimpan dalam hal ini, tidak ada perbandingan (tentu saja). Saya yakin kami bisa men-tweak basis kode di sana-sini untuk meningkatkan kinerjanya, namun, dalam hal ini kami hanya memerlukan peningkatan kinerja tanpa analisis karena kendala waktu, dan kami kembali ke proc yang disimpan (masih memetakannya melalui EF, karena EF memberikan hasil yang sangat diketik), kami hanya membutuhkan itu sebagai jatuh kembali di beberapa daerah. Ketika kami harus menelusuri seluruh basis data untuk membuat koleksi (menggunakan .include () tanpa tanggung jawab), kinerjanya terasa menurun, tapi mungkin kami terlalu banyak bertanya ..

Jadi berdasarkan pengalaman saya, saya akan merekomendasikan membuat .edmx terpisah per niat. Hanya hasilkan apa yang akan Anda gunakan berdasarkan ruang lingkup kebutuhan itu. Anda mungkin memiliki beberapa file .edmx yang dicakup lebih kecil untuk tugas yang bertujuan, dan kemudian beberapa yang besar di mana Anda perlu melintasi hubungan kompleks untuk membangun objek. Saya tidak yakin di mana tempat sihir itu, tapi saya yakin ada satu ... lol ...

Jujur saja, selain dari beberapa jebakan yang menurut kami agaknya datang (melintasi rumit), .edmx besar bekerja dengan baik dari perspektif "bekerja". Tapi Anda harus berhati-hati dengan sihir "fixup" yang konteksnya lakukan di belakang layar jika Anda tidak menonaktifkannya secara eksplisit. Serta menjaga .edmx dalam sinkronisasi ketika perubahan ke database dibuat .. terkadang lebih mudah untuk menghapus seluruh permukaan dan membuat ulang entitas, yang membutuhkan waktu 3 menit sehingga itu bukan masalah besar.

Ini semua dengan EntityFramework 4.1. Saya akan sangat tertarik mendengar tentang pilihan dan pengalaman akhir Anda juga.

Dan mengenai pertanyaan Anda di nHibernate, itu pertanyaan tentang cacing, menurut pendapat saya, Anda akan menggonggong di kedua sisi pagar ... Saya mendengar banyak orang menampar EF demi bashing tanpa bekerja melalui tantangan dan memahami nuansa unik untuk EF itu sendiri .. dan meskipun saya belum pernah menggunakan nHibernate dalam produksi, secara umum, jika Anda harus secara manual dan eksplisit membuat hal-hal seperti pemetaan, Anda akan mendapatkan kontrol yang lebih terbatas, namun, jika Anda dapat menyeret n 'drop, menghasilkan, dan mulai CRUD'ing dan query menggunakan LINQ, saya bisa memberikan omong kosong tentang granularity.

Saya harap ini membantu.


1
FYI - Ada Utilitas Pemetaan NHibernate yang membuat pemetaan ini SANGAT mudah, dan otomatis.
ganders

@ ganders - Apakah ia memiliki UI dan bagaimana integrasi IDE-nya? Saya berasumsi Anda mengarahkannya ke sumber data dan menghormati integritas referensial dan objek traversal dan membuat objek pemetaan?
hanzolo

1
Ya itu (GUI). Sejauh ini saya tidak memiliki masalah dengannya. Digunakan pada 4 atau 5 proyek / situs web yang berbeda. Catatan: Saya menggunakannya dengan Fluent NHibernate, yang melakukan pemetaan dalam kode c #, bukan dalam file config / xml. Berikut tautannya: nmg.codeplex.com
ganders

13

Biarkan saya mulai dengan klarifikasi sederhana: Saya tidak memiliki pengalaman dengan database yang begitu besar sehingga sisa jawaban saya tidak didasarkan pada contoh dunia nyata.

Jadi Anda memiliki basis data BESAR dan Anda ingin menggunakannya dengan ORM / EF. Saya akan memilih yang kedua. Inilah penjelasan sederhana saya mengapa:

  • Pemetaan menambah kompleksitas. Tidak perlu menambah kerumitan dengan entitas aplikasi / proyek / modul Anda saat ini tidak pernah perlu tetapi jangan membuat granularity tingkat terlalu rendah. Menetapkan pemetaan terpisah per layar tidak akan membantu Anda juga.
  • Anda ingin mencapai unit kerja. Anda harus dapat menentukan tabel apa yang dibutuhkan modul dalam kebanyakan kasus (tidak perlu dalam semua kasus). Jika Anda menempatkan tabel ini ke dalam set pemetaan tunggal, Anda akan dapat menangani pembacaan dan modifikasi data dengan instance konteks tunggal - itulah yang harus menjadi target utama Anda.
  • Saya tidak yakin apa yang sebenarnya Anda maksudkan dengan model tetapi bahkan dengan set pemetaan yang berbeda Anda dapat berbagi kelas antara set pemetaan menggunakan tipe entitas yang sama. Jadi jika Anda menggunakan tabel Pengguna dalam dua modul Anda tidak perlu dua kelas Pengguna untuk mewakili yang sama. Anda masih dapat menggunakan tabel tunggal dan dalam hal pemetaan kode (alias kode-pertama) Anda bahkan dapat mendefinisikan pemetaan sekali dan memuatnya ke beberapa set pemetaan sehingga prinsip KERING tidak dilanggar tetapi pendekatan kode-pertama memiliki batasan lebih ketika datang untuk melihat dan menyimpan prosedur. EDMX membuat ini lebih sulit. Anda masih dapat menggunakan kembali kelas tetapi menggunakan kembali pemetaan tidak mungkin.
  • Bagaimana dengan pertanyaan lintas modul? Pertanyaan-pertanyaan ini mungkin terjadi tetapi jujur ​​saja tidak semuanya harus ditangani oleh EF. Anda dapat mengambil keuntungan dari EF untuk kasus-kasus umum untuk menyederhanakan akses data biasa tetapi jika Anda membutuhkan tempat khusus untuk permintaan yang menggabungkan tabel-tabel milik 5 modul yang berbeda, Anda dapat langsung menjalankannya atau membungkusnya dengan prosedur tersimpan. Penggantian 100% akses data asli bisa sulit, rumit dan kontraproduktif.
  • Poin terakhir cukup praktis: Saya tidak percaya bahwa VS tooling siap untuk bekerja dengan sekumpulan objek besar - tidak pada perancang, bahkan dengan alat impor. Saya dulu bekerja pada database yang sangat besar dengan akses data tradisional dan proyek SQL Database di VS2008 - pengalaman pengguna dengan proyek yang kompleks sangat buruk. Anda harus menjaga agar jumlah tabel yang digunakan rendah - batas untuk desainer harus berada di antara 100-200 tetapi bahkan 100 tabel ditangani oleh konteks tunggal (set pemetaan) terdengar seperti terlalu banyak tanggung jawab untuk satu kelas (misalkan Anda akan memiliki 100 set properti terbuka pada konteks - tidak terlihat seperti desain yang bagus).

4

Saya akan mengatakan Anda tidak dapat memutuskan pertanyaan semacam ini dari perspektif teknis. Saya akan merekomendasikan agar Anda membangun arsitektur berdasarkan kasus penggunaan Anda (cerita pengguna, dll.). Pertama temukan objek bisnis Anda. Objek entitas tidak sesuai standar objek bisnis. Biasanya Anda akan memiliki objek bisnis di depan objek entitas. Kemudian Anda dapat secara bertahap memutuskan apa yang benar-benar Anda butuhkan, berdasarkan kebutuhan pengguna.

"Arsitek yang baik memaksimalkan jumlah keputusan yang tidak dibuat." Robert C. Martin

http://cleancoder.posterous.com/architecture-deference


3

Saya menggunakan pendekatan hibrid - hal-hal OLTP ditangani oleh EF sementara operasi berat seperti sisipan bets, pembaruan massal, kueri laporan, dll. Ditangani oleh Stored Procs. Itu juga membuat jalur migrasi lebih mudah jika Anda tidak melakukan penulisan ulang penuh dari lapisan data Anda sekaligus.


Ini sepertinya strategi yang bagus, tetapi tidak benar-benar menjawab pertanyaan tentang bagaimana membagi entitas di berbagai model EF. Apakah Anda memiliki semua entitas dalam satu model atau apakah Anda membagi dan menaklukkan dengan cara tertentu?
RationalGeek

1
Jika kinerja OLTP memadai dengan pendekatan model penuh, ikuti saja. Anda selalu dapat memecahnya nanti jika Anda harus, tetapi cara tercepat dan paling gesit adalah memuat semuanya. Anda mungkin tidak pernah membutuhkan peningkatan kinerja yang Anda dapatkan dengan memecahnya, sehingga Anda akan membuang waktu dan membuat sistem Anda lebih rumit tanpa alasan. Lalu ada pertanyaan model mana yang akan Anda tempel tabel / entitas baru ketika Anda memutuskan untuk memperluas. Dan apa yang terjadi ketika Anda perlu menjalankan pembaruan di berbagai model. Selamatkan diri Anda dari sakit kepala kecuali Anda benar-benar tidak memiliki alternatif.
Nik

Lupa menyebutkan bahwa Anda selalu dapat mengubah kinerja saat mengakses data. Lihatlah opsi pemuatan malas / bersemangat dan entitas anak mana yang Anda bawa. Saya tidak melihat alasan mengapa model lengkap akan berperilaku lebih buruk daripada yang lebih kecil jika Anda tidak memuat pohon objek besar.
Nik

saya akan mengatakan pohon objek besar dan struktur data yang dinormalisasi berjalan seiring ketika berhadapan dengan skema besar
hanzolo

Anda mengontrol seberapa sedikit atau seberapa banyak Anda ingin menjenuhkan grafik objek.
Nik
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.