Praktik terbaik untuk meminta data dari MS SQL Server di C #?

9

Apa cara terbaik untuk meminta data dari MS SQL Server di C #?

Saya tahu bahwa bukan praktik yang baik untuk memiliki kueri SQL dalam kode.

Apakah cara terbaik untuk membuat prosedur tersimpan dan menyebutnya dari C # dengan parameter?

using (var conn = new SqlConnection(connStr))
using (var command = new SqlCommand("StoredProc", conn) { CommandType = CommandType.StoredProcedure }) {
   conn.Open();
   command.ExecuteNonQuery();
   conn.Close();
}
Bruno
sumber
8
"Saya tahu itu bukan praktik yang baik untuk memiliki kueri SQL dalam kode." - Imo, itu omong kosong.
GrandmasterB
4
Anda tidak perlu memanggil conn.Close () jika Anda membuatnya dalam blok using. Inti dari blok yang digunakan adalah untuk meniru gaya C ++ dari destructor clean up. Pembersih elegan dari zaman yang lebih beradab. Tidak acak atau sembrono seperti gaya try-catch.
Lord Tydus
2
FYI. Prosedur tersimpan juga "kode". Inti dari procs yang disimpan adalah untuk memungkinkan pencampuran kode prosedural dengan set-style style SQL. Jadi, Anda akan memiliki kueri dalam kode apa pun. Untuk aplikasi dengan volume yang sangat tinggi kadang-kadang lebih baik memiliki logika yang dilakukan di luar database untuk memungkinkan penskalaan horizontal dengan menambahkan server. Jika Anda dapat mempertahankan DB tunggal, tetapi muli-server untuk logika maka penskalaan menjadi lebih mudah.
Lord Tydus
@GrandmasterB kami memiliki sejumlah besar inline SQL dalam C # (C # LOC kami sudah mendekati 2 juta sekarang) - dan 6 tahun kemudian ia kembali menggigit kami karena kami sekarang perlu memburu SQL inline itu (kami baru-baru ini menyewa seorang ahli SQL - jadi kami melakukan tweak kinerja). Percayalah: Anda tidak pernah tahu seberapa besar aplikasi Anda dan bagaimana hal-hal akan berubah di masa depan. Simpan berbagai bahasa dalam file yang berbeda - bahkan jika Anda hanya mendelegasikannya ke sumber nyata. Anda juga bisa // SQLCODEmelakukannya - tetapi Anda harus ingat untuk melakukan itu.
Jonathan Dickinson
1
@ JonathanDickinson, Gunakan procs yang disimpan jika Anda mau. Saya telah mengatakan berkali-kali mereka berguna ketika Anda memiliki basis kode yang berbeda yang beroperasi terhadap database yang sama. Tetapi hanya karena mereka berguna dalam beberapa keadaan tidak secara otomatis membuat mereka tidak menggunakan 'praktik buruk' sepanjang waktu . Jika menggunakan pernyataan SQL secara langsung tidak menyebabkan masalah, maka itu bukan 'praktik buruk' untuk aplikasi itu.
GrandmasterB

Jawaban:

10

Menggunakan prosedur tersimpan adalah salah satu cara, dan telah digunakan secara luas selama bertahun-tahun.

Cara yang lebih modern untuk berinteraksi dengan database SQL Server dari C # (atau bahasa NET.) Adalah dengan menggunakan Entity Framework. Keuntungan dari Entity Framework adalah memberikan tingkat abstraksi yang lebih tinggi.

Mengutip dari Microsoft ( https://msdn.microsoft.com/en-us/data/jj590134 ):

ADO.NET Entity Framework memungkinkan pengembang untuk membuat aplikasi akses data dengan pemrograman terhadap model aplikasi konseptual alih-alih pemrograman langsung terhadap skema penyimpanan relasional. Tujuannya adalah untuk mengurangi jumlah kode dan pemeliharaan yang diperlukan untuk aplikasi berorientasi data. Aplikasi Entity Framework memberikan manfaat berikut:

  • Aplikasi dapat bekerja dalam hal model konseptual yang lebih berpusat pada aplikasi, termasuk tipe dengan pewarisan, anggota yang kompleks, dan hubungan.
  • Aplikasi dibebaskan dari dependensi kode keras pada mesin data atau skema penyimpanan tertentu.
  • Pemetaan antara model konseptual dan skema penyimpanan khusus dapat berubah tanpa mengubah kode aplikasi.
  • Pengembang dapat bekerja dengan model objek aplikasi yang konsisten yang dapat dipetakan ke berbagai skema penyimpanan, mungkin diimplementasikan dalam sistem manajemen basis data yang berbeda.
  • Beberapa model konseptual dapat dipetakan ke skema penyimpanan tunggal.
  • Dukungan kueri terintegrasi bahasa (LINQ) menyediakan validasi waktu kompilasi sintaksis untuk kueri terhadap model konseptual.

Penggunaan ORM vs Stored Procedures melibatkan pengorbanan, khususnya dalam hal keamanan dan di mana logika berada.

Pendekatan "klasik" untuk pengembangan dengan SQL Server adalah memiliki logika aplikasi berada dalam prosedur tersimpan dan program hanya diberi hak keamanan untuk menjalankan prosedur tersimpan, bukan memperbarui tabel secara langsung. Konsepnya di sini adalah bahwa prosedur tersimpan adalah lapisan logika bisnis untuk aplikasi. Sementara teorinya sehat, ia cenderung tidak disukai karena berbagai alasan, digantikan dengan menerapkan logika bisnis dalam bahasa pemrograman seperti C # atau VB. Aplikasi yang baik masih diimplementasikan dengan pendekatan berjenjang, termasuk pemisahan masalah dll. Tetapi lebih cenderung mengikuti pola seperti MVC.

Salah satu kelemahan menerapkan logika dalam ORM daripada database adalah kemudahan debugging dan menguji aturan integritas data oleh mereka yang bertanggung jawab untuk database (DA atau DBA). Ambil contoh klasik mentransfer uang dari giro Anda ke rekening tabungan, penting bahwa ini dilakukan sebagai unit atom, dengan kata lain diapit dalam suatu transaksi. Jika transfer semacam ini hanya diperbolehkan dilakukan melalui prosedur tersimpan, relatif mudah bagi DA dan auditor untuk QA prosedur tersimpan.

Jika di sisi lain ini dilakukan melalui ORM seperti Entity Framework dan dalam produksi diketahui bahwa jarang terjadi uang diambil dari pengecekan tetapi tidak dimasukkan ke dalam debugging tabungan mungkin jauh lebih kompleks, terutama jika beberapa program berpotensi terlibat. Ini kemungkinan besar akan menjadi kasus tepi, mungkin melibatkan masalah perangkat keras khusus yang perlu terjadi dalam urutan tertentu dll. Bagaimana cara seseorang menguji ini?

JonnyBoats
sumber
Atau ORM lainnya. Ada banyak dari mereka, dengan berbagai kelebihan dan kekurangan jika dibandingkan dengan EF.
svick
8
Kerugian listing ORM akan membuat jawaban ini lebih bermanfaat.
Den
6

Sebenarnya pernyataan dasar masih bisa diperdebatkan - ada pertukaran baik cara antara memiliki SQL dalam kode atau memiliki kode dalam database (yang mana Anda menuju dengan prosedur tersimpan).

Hasilnya adalah bahwa tidak ada satu pun "yang terbaik", ini bukan sesuatu yang dapat digeneralisasi karena ke mana pun Anda pergi, Anda membuat kompromi (Anda mendapatkan manfaat tetapi juga memperkenalkan kendala).

Jika ada korespondensi satu ke satu antara aplikasi Anda dan basis data Anda, maka itu tidak masalah. Jika, di sisi lain, Anda memiliki basis data inti besar yang dibagikan oleh sejumlah besar aplikasi yang menegakkan konsistensi di dalam basis data di antara aplikasi-aplikasi itu menjadi jauh lebih penting.

Yang lebih penting adalah khawatir tentang arsitektur dan pelapisan aplikasi Anda - diberi lapisan akses data yang tepat apakah menggunakan ORM seperti Entity Framework atau NHibernate atau melakukan sesuatu yang lebih langsung harus mengisolasi sebagian besar aplikasi Anda dari keputusan ini, terlepas dari apakah Anda membuat kueri atau gunakan prosedur tersimpan.


Saya akan dengan bebas, saya cenderung bekerja pada proyek yang relatif kecil dengan tim kecil (1-3 devs) - menggunakan prosedur tersimpan, bagi saya, lebih banyak masalah daripada nilainya karena mengingat sifat aplikasi kita (dan skillet saya?) Menyebarkan baru kode umumnya jauh lebih mudah daripada memperbarui skema (bahkan memungkinkan saya memiliki kode yang membuat memperbarui skema relatif mudah) dan saya dapat menegakkan aturan bisnis dengan menggunakan kode akses data umum. Ini jelas merupakan contoh klasik dari "Your Mileage May Vary".

Murph
sumber
2
+1 untuk "no single best", -1 untuk menyebarkan kode lebih mudah daripada menggunakan perubahan proc yang tersimpan, +1 untuk memilih pendekatan yang masuk akal untuk aplikasi Anda dan memastikan isolasi DAL - Jadi +1.
Joel Brown
Saya memang memenuhi syarat untuk menggunakan bit "untuk saya" karena itu bagi saya secara konsisten menjadi masalah (terutama untuk aplikasi web) - untuk semua yang mungkin ada sedikit penulisan ulang di area itu.
Murph
+1, apa yang terbaik tergantung pada aplikasi & situasi.
GrandmasterB
1
Saya kira itu tergantung pada kondisi tempat Anda bekerja. Jika Anda tidak memiliki DBA yang mengunci Anda dari produksi, menjatuhkan proc yang tersimpan ke dalam basis data bisa menjadi sangat mudah. Untuk itu, tanpa kontrol produksi menjatuhkan markup baru, skrip dan bahkan kode kompilasi baru ke dalam aplikasi terpusat juga bisa menjadi terlalu mudah.
Joel Brown
@ JoelBrown - Tepat - saya kira, tidak, saya yakin saya membuat banyak asumsi di sana. Pertama skema saya adalah versi terkontrol (dengan cara kasar tapi efektif), saya bukan dba tapi saya cukup pintar untuk mengetahui bahwa skema seseorang harus konsisten. Saya bekerja pada sebagian besar pada aplikasi web dan Anda tidak dapat mengakses database kecuali dengan mengunjungi server, sedangkan saya (hanya) mengurangi penyebaran aplikasi menjadi (lebih atau kurang) satu klik tombol ... mengintegrasikan pembaruan skema ke dalam kata penyebaran ada di daftar, tetapi saya selalu menemukan pembaruan skema lebih menegangkan daripada pembaruan kode (kemudahan rollback?)
Murph
4

Selama Anda telah menetapkan input Anda, pendekatan apa pun valid. Sebagian besar tidak memiliki pertanyaan dalam argumen kode yang berasal dari masa lalu yang buruk ketika banyak perpustakaan memaksa Anda untuk menambahkan pernyataan Anda bersama-sama dan dari situlah serangan injeksi sql berasal.

Tagihan
sumber
1
Apakah parameterisasi cukup? Apakah kamu tidak perlu membersihkan juga?
StuperUser
itu tergantung pada sumber dan tujuan Anda. Saya menerima pertanyaannya secara harfiah, dia hanya baca dengan beberapa parameter. dalam kasus umum yang terburuk yang akan Anda lakukan dengan input kotor jika parametrized dengan benar adalah mendapatkan jenis pengecualian atau tidak ada hasil dengan input buruk. Memasukkan berbeda dan biasanya memerlukan validasi kecuali Anda memperlakukan sumber sebagai otoritatif.
Bill
0

Praktik terbaik benar-benar berlebihan di sini - ada banyak cara bagus untuk melakukannya dan yang Anda pilih benar-benar harus bergantung pada apa aplikasi Anda dan apa yang perlu Anda lakukan. Yang mengatakan, hanya ada dua hal yang dapat Anda lakukan salah:

  • Seperti yang ditunjukkan oleh @Bill, Anda harus selalu membuat parameter pertanyaan Anda. String building adalah vektor yang mudah untuk injeksi SQL dan juga segala macam kesulitan untuk melacak bug. Banyak orang yang lebih pintar menemukan cara untuk meluputkan dan melarikan diri dari sql sehingga Anda tidak perlu mencari tahu sendiri.

  • Tutup koneksi Anda. Cara terbaik adalah untuk membungkus segala sesuatu dengan menggunakan pernyataan, tetapi coba / tangkap / akhirnya keren juga jika itu mengapung perahu Anda. Tetapi selalu pastikan Anda menggunakan koneksi seperti mobil murah - mengendarainya dengan keras dan cepat dan menyingkirkannya dengan cepat.

Praktik lain yang akan saya perdebatkan adalah bahwa Anda harus memastikan untuk berkonsentrasi kode akses data Anda di tempat sesedikit mungkin. Kami tidak mengizinkan aplikasi web front-end untuk memegang referensi langsung ke System.Data.SqlClient untuk membantu menegakkan peringatan ini.

Wyatt Barnett
sumber