NHibernate - Panduan Cepat

Pada bab ini kita akan membahas tentang apa itu NHibernate, platform apa saja yang dapat diimplementasikan, apa saja kelebihannya dan aspek lain yang terkait dengannya.

Apa itu NHibernate?

NHibernate adalah pemeta relasional objek open source yang matang untuk framework .NET. Ini secara aktif dikembangkan, berfitur lengkap dan digunakan dalam ribuan proyek yang sukses. Itu dibangun di atasADO.NET dan versi saat ini adalah NHibernate 4.0.4.

  • NHibernate adalah pemeta relasional objek .NET open-source dan didistribusikan di bawah GNU Lesser General Public License.

  • Ini didasarkan pada Hibernate yang merupakan pemeta relasional objek Java yang populer dan memiliki basis kode yang sangat matang dan aktif.

  • Ini menyediakan kerangka kerja untuk memetakan model domain berorientasi objek ke database relasional tradisional.

  • NHibernate dimulai oleh Tom Barrett dan proyek ini telah ada sejak Februari 2003, yang merupakan komitmen pertama mereka.

  • Ini adalah proyek besar dan menyediakan banyak fungsi.

  • Ada sebuah NuGet package tersedia, yang membuatnya sangat mudah untuk ditambahkan ke proyek.

Mengapa NHibernate?

Sekarang pertanyaannya adalah mengapa kita membutuhkannya object-relational mappers? Itu karena ada keterputusan antara dunia objek dan dunia relasional.

  • Di dunia objek, semuanya didasarkan pada objects; kami menyebut objek hal-hal yang memiliki data kami.

  • Dunia relasional semuanya berbasis set dan kita berurusan dengan tabel dan baris yang berbeda dari dunia objek.

  • Di dunia objek, kita punya unidirectional associations. Jika pelanggan memiliki penunjuk ke pesanan, itu tidak berarti bahwa pesanan memiliki penunjuk kembali ke pelanggan, mungkin atau mungkin tidak.

  • Dalam dunia relasional, semua asosiasi adalah bidirectional dan itu bisa dilakukan dengan kunci asing.

  • Semua asosiasi secara inheren dua arah, jadi ketika kita berurusan dengan pemetaan relasional objek, kita juga perlu berurusan dengan pemutusan ini.

  • Di dunia objek, kami bekerja dengan pointer yang searah, sedangkan dengan dunia relasional, kami memiliki kunci asing yang secara inheren dua arah.

  • Dunia benda memiliki pengertian warisan ini, di mana kendaraan dapat memiliki sejumlah subkelas yang berbeda, jadi mobil adalah jenis kendaraan, perahu adalah jenis kendaraan, dan mobil sport adalah jenis mobil, jenis-jenis ini hubungan warisan.

  • Dunia relasional tidak memiliki gagasan tentang warisan ini.

Pemetaan

Jadi bagaimana kita memetakan semua ini disjoint relationships?Konsep pemetaan ini berasal dari pemeta relasional objek. Terutama ada tiga hal yang perlu dipahami seperti yang ditunjukkan pada diagram berikut.

  • Dalam aplikasi Anda, Anda memerlukan definisi kelas, yang biasanya berupa kode C # dan kode .NET-nya yang mewakili kelas kita, seperti kelas Karyawan, kelas Pelanggan, kelas Order, dll.

  • Di bagian bawah, Anda dapat melihat skema database, yang merupakan milik kami Data Definition Language dalam database relasional yang menentukan seperti apa tabel pelanggan, seperti apa tabel karyawan itu.

  • Di antara ini kami memiliki metadata pemetaan yang memberitahu pemeta objek-relasional bagaimana menerjemahkan dari dunia objek di C # ke dunia database dalam hal baris dan kolom dan hubungan kunci asing.

  • Metadata pemetaan ini dapat direpresentasikan dalam berbagai cara berbeda dan kita akan melihat sejumlah cara berbeda yang paling umum digunakan dalam aplikasi NHibernate.

  • Itu diwakili oleh HBM (Hibernate Mapping) file, yang merupakan file XML.

Database yang Didukung

NHibernate mendukung berbagai macam database yang berbeda. Setiap database relasional yang ada di luar sana dapat diakses ke NHibernate.

  • SQL server adalah basis data utama yang didukung, itulah yang digunakan sebagian besar pengembang selama pengembangan, mungkin itu yang paling umum.

  • Juga works very well with Oracle.

  • Ini juga mendukung DB2, Firebird, MySQL, PostgreSQL, SQL Lite

  • Ia juga memiliki ODBC and OLEDB drivers.

Sekarang-a-hari, banyak sistem dirancang dengan arsitektur berlapis, NHibernate juga memilikinya dan bekerja dengan sangat baik dengan desain itu.

Arsitektur Berlapis

Arsitektur berlapis membagi sistem menjadi beberapa grup, di mana setiap grup berisi kode yang menangani area masalah tertentu dan grup ini disebut lapisan. Sebagian besar penggunaan aplikasi tingkat perusahaanhigh-level application architecture yang terdiri dari tiga lapisan -

  • Lapisan Presentasi
  • Lapisan Bisnis
  • Lapisan Persistensi

Misalnya, lapisan antarmuka pengguna yang juga dikenal sebagai lapisan presentasi mungkin berisi semua kode aplikasi untuk membangun halaman web dan memproses masukan pengguna.

Salah satu keuntungan utama dari pendekatan pelapisan adalah Anda sering dapat membuat perubahan pada satu lapisan tanpa gangguan yang berarti pada lapisan lainnya, sehingga membuat sistem lesser fragile and more maintainable.

Lapisan Presentasi

  • Ini adalah lapisan paling atas, yang berisi kode yang bertanggung jawab untuk menggambar Antarmuka Pengguna, halaman, dialog atau layar, dan mengumpulkan input pengguna, dan mengontrol navigasi.

Lapisan Bisnis

  • Lapisan bisnis bertanggung jawab untuk menerapkan aturan bisnis atau persyaratan sistem apa pun yang akan dipahami pengguna sebagai bagian dari domain masalah.

  • Ini juga menggunakan kembali model yang ditentukan oleh lapisan persistensi.

Lapisan Persistensi

  • Lapisan persistensi terdiri dari kelas dan komponen yang bertanggung jawab untuk menyimpan dan mengambil data aplikasi.

  • Lapisan ini juga mendefinisikan pemetaan antara kelas model dan database. NHibernate digunakan terutama di lapisan ini.

Database

  • Basis data ada di luar aplikasi .NET.
  • Ini adalah representasi aktual dari status sistem.
  • Jika database SQL digunakan, database menyertakan skema relasional dan kemungkinan prosedur tersimpan.

Kelas Pembantu / Utilitas

  • Setiap aplikasi memiliki sekumpulan kelas pembantu atau utilitas yang mendukung lapisan lain: misalnya, widget UI, kelas perpesanan, kelas pengecualian, dan utilitas logging.

  • Elemen-elemen ini tidak dianggap sebagai lapisan, karena mereka tidak mematuhi aturan untuk ketergantungan interlayer dalam arsitektur berlapis.

Arsitektur NHibernate

  • Ini adalah tampilan tingkat tinggi dari aplikasi NHibernate dan Anda juga dapat melihat arsitektur NHibernate sederhana.

  • Kode aplikasi menggunakan NHibernate ISession dan IQuery API untuk operasi persistensi dan hanya perlu mengelola transaksi database, idealnya menggunakan NHibernate ITransaction API.

Sebelum kita benar-benar dapat mulai menggunakan NHibernate, kita perlu memahami fondasi yang dibangunnya. NHibernate adalah teknologi ketekunan yang didasarkan pada gagasan pemetaan relasional objek atau ORM.

Apa itu ORM?

Object-Relational Mapping (ORM) adalah a programming techniqueuntuk mengubah data antara sistem tipe yang tidak kompatibel dalam bahasa pemrograman berorientasi objek. Dengan kata lain, ini adalah konsep pemetaan objek bisnis aplikasi ke tabel database relasional, sehingga data dapat dengan mudah diakses dan diperbarui seluruhnya melalui model objek aplikasi.

  • Seperti yang telah Anda ketahui bahwa database relasional menyediakan sarana yang baik untuk menyimpan data, sedangkan pemrograman berorientasi objek adalah pendekatan yang baik untuk membangun aplikasi yang kompleks.

  • NHibernate dan ORM secara umum paling relevan dengan aplikasi dengan logika bisnis nontrivial, model domain, dan semacam database.

  • Dengan ORM, sangat mudah untuk membuat lapisan terjemahan yang dapat dengan mudah mengubah objek menjadi data relasional dan kembali lagi.

  • Akronim ORM juga dapat berarti pemodelan peran objek, dan istilah ini ditemukan sebelum pemetaan objek / relasional menjadi relevan.

  • Ini menjelaskan metode analisis informasi, yang digunakan dalam pemodelan database.

Mengapa ORM?

ORM adalah framework yang memungkinkan Anda memetakan dunia objek yang ditemukan dalam bahasa berorientasi objek ke baris dalam tabel relasional yang ditemukan dalam database relasional

Untuk memahami konsep ini, mari kita lihat diagram berikut.

  • Pada diagram di atas, Anda dapat melihat bahwa kami memiliki tabel bernama Karyawan di sisi kanan yang berisi kolom dengan setiap bagian data yang terkait dengan karyawan individu.

  • Kami memiliki kolom untuk Id yang secara unik mengidentifikasi setiap karyawan.

  • Kolom untuk nama karyawan, kolom lain untuk tanggal bergabung, dan terakhir kolom yang berisi usia karyawan.

  • Jika kita ingin menulis beberapa kode untuk menyimpan karyawan baru di tabel, tidaklah mudah.

  • Pada diagram di atas, Anda juga dapat melihat bahwa kami memiliki objek karyawan yang memiliki bidang untuk Id, nama, tanggal dan usia bergabung.

  • Tanpa ORM kita harus menerjemahkan objek ini ke dalam beberapa pernyataan SQL berbeda yang akan memasukkan data pegawai ke dalam tabel pegawai.

  • Jadi menulis kode untuk membuat SQL untuk melakukan skenario di atas tidak terlalu sulit, tetapi agak membosankan dan mudah membuat kesalahan.

  • Dengan menggunakan ORM seperti NHibernate, kita dapat mendeklarasikan bagaimana kelas tertentu harus dipetakan ke tabel relasional dan membiarkan ORM atau NHibernate menangani pekerjaan buruk membuat SQL untuk menyisipkan, memperbarui, menghapus, dalam data kueri di tabel karyawan kita.

  • Ini memungkinkan kita untuk menjaga kode kita tetap fokus pada penggunaan objek dan objek tersebut secara otomatis diterjemahkan ke tabel relasional.

  • Jadi sebenarnya yang dilakukan ORM adalah menyelamatkan kita dari keharusan memetakan objek ke tabel secara manual.

Untuk mulai mengerjakan NHibernate, kita membutuhkan Visual Studio dan paket NHibernate.

Penginstalan Visual Studio

Microsoft menyediakan free version Visual Studio, yang juga berisi SQL Server dan dapat diunduh dari https://www.visualstudio.com Berikut langkah-langkah penginstalannya.

Step 1 - Setelah pengunduhan selesai, jalankan penginstal, kemudian kotak dialog berikut akan ditampilkan.

Step 2 - Klik pada tombol Install dan itu akan memulai proses instalasi.

Step 3 - Setelah proses instalasi selesai dengan sukses, Anda akan melihat kotak dialog berikut.

Step 4 - Tutup kotak dialog ini dan restart komputer Anda jika diperlukan.

Step 5- Sekarang buka Visual studio dari Start Menu yang akan membuka dialog berikut. Ini akan memakan waktu untuk pertama kalinya untuk persiapan.

Step 6 - Setelah semua ini selesai, Anda akan melihat jendela utama Visual Studio.

Instalasi Paket NHibernate

NHibernate adalah pemeta relasional objek open source yang matang untuk framework .NET. Ini secara aktif dikembangkan, berfitur lengkap dan digunakan dalam ribuan proyek yang sukses. Anda dapat menginstal paket NHibernate dengan metode berikut.

Unduh langsung

  • Unduh zip dari file dari https://sourceforge.net/ yang berisi semua binari yang diperlukan.

  • Ekstrak file zip ini dan sertakan semua biner ini dalam proyek Anda.

Instal Menggunakan NuGet

  • Cara lain untuk menginstal NHibernate adalah dengan menggunakan NuGet untuk menginstal paket NHibernate, yang sejauh ini merupakan cara termudah untuk memasukkan NHibernate ke dalam sebuah proyek.

  • Ini akan mengunduh semua dependensi NHibernate dan membuat referensi ke semua rakitan yang diperlukan.

  • Untuk menginstal NHibernate, jalankan perintah berikut di Package Manager Console.

install-package NHibernate

Anda sekarang siap untuk memulai aplikasi Anda.

Dalam bab ini, kita akan melihat bagaimana memulai contoh sederhana menggunakan NHibernate. Kami akan membangun asimple console application. Untuk membuat aplikasi konsol, kami akan menggunakan Visual Studio 2015, yang berisi semua fitur yang Anda butuhkan untuk membuat, uji aplikasi Anda menggunakan paket NHibernate.

Berikut adalah langkah-langkah untuk membuat proyek menggunakan templat proyek yang tersedia di Visual Studio.

Step 1 - Buka Visual studio dan klik File → New → Project menu option.

Step 2 - Dialog Proyek baru terbuka.

Step 3 - Dari panel kiri, pilih Template → Visual C # → Windows.

Step 4 - Di panel tengah, pilih Aplikasi Konsol.

Step 5 - Masukkan nama proyek, 'NHibernateDemoApp', di bidang Nama dan klik Oke untuk melanjutkan.

Step 6 - Setelah proyek dibuat oleh Visual Studio, Anda akan melihat sejumlah file yang ditampilkan di jendela Solution Explorer.

Seperti yang Anda ketahui bahwa kami telah membuat proyek aplikasi konsol sederhana, sekarang kami perlu menyertakan paket NHibernate ke proyek konsol kami.

Buka menu Tools dan pilih NuGet Package Manager → Package Manager Console, itu akan membuka jendela Package Manager Console.

Tentukan perintah yang ditunjukkan di atas Package Manager Consolejendela dan tekan enter, itu akan mengunduh semua dependensi NHibernate dan membuat referensi ke semua majelis yang diperlukan. Setelah instalasi selesai, Anda akan melihat pesan seperti yang ditunjukkan pada gambar berikut.

Sekarang setelah kami menambahkan NHibernate, sekarang kami dapat memulai implementasi. Jadi, kami akan memulai dengan memetakan yang sangat sederhanatable dipanggil Student, yang hanya memiliki kunci primer integer yang disebut ID dan kolom NamaDepan dan NamaBelakang.

Kita membutuhkan kelas untuk mewakili siswa ini, jadi mari buat kelas baru bernama Siswa dengan mengklik kanan pada proyek di explorer solusi dan kemudian pilih Tambah → Kelas yang akan membuka kotak dialog Tambah Item Baru.

Memasukkan Student.csdi bidang nama, klik tombol Tambah. Di kelas Mahasiswa ini, kita perlu memiliki kunci primer integer yang disebut ID, dan kita perlu membuat string ini,FirstName dan LastName bidang seperti yang ditunjukkan dalam implementasi lengkap kelas Mahasiswa berikut.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks;

namespace NHibernateDemoApp { 
   
   class Student { 
      public virtual int ID { get; set; } 
      public virtual string LastName { get; set; } 
      public virtual string FirstMidName { get; set; } 
   } 
}

Saat menangani model dalam aplikasi NHibernate, paling mudah untuk menjadikan semua bidang Anda virtual. Jadi ini adalah model NHibernate sederhana yang akan kita gunakan dan akan memetakannya ke database back end.

Sekarang mari kita pergi ke metode Utama di kelas Program dan membuat objek konfigurasi NHibernate baru.

Hal pertama yang perlu kami sediakan adalah connection string. Ini adalah string koneksi khusus database dan cara termudah untuk menemukan string koneksi adalah dengan mengklik kanan pada database diSQL Server Object Explorer dan pilih Properties.

Ini akan membuka Jendela Properties, sekarang gulir ke bawah dan Anda akan melihat bidang Connection String di jendela Properties.

Salin string Koneksi dan tentukan dalam kode Anda. Berikut adalah implementasi metode utama yang memerlukan konfigurasi untuk NHibernate.

using NHibernate.Cfg;
using NHibernate.Dialect;
using NHibernate.Driver;

using System;
using System.Linq;
using System.Reflection;

namespace NHibernateDemoApp {

   class Program {
   
      static void Main(string[] args) {
         var cfg = new Configuration();
			
         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;
			
         cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + 
            Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
            TrustServerCertificate + ApplicationIntent + MultiSubnetFailover";
         
                     
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>();
         });
         
         cfg.AddAssembly(Assembly.GetExecutingAssembly());
         
         var sefact = cfg.BuildSessionFactory(); 
         
         using (var session = sefact.OpenSession()) {
         
            using (var tx = session.BeginTransaction()) {
               //perform database logic 
               tx.Commit();
            }
            
            Console.ReadLine(); 
         } 
      } 
   } 
}

Setelah koneksi string, kita perlu menyediakan driver, yaitu SQLClientDriver dan kemudian kita juga perlu memberinya dialek, versi SQL Server yang mana, dan kita akan menggunakan MS SQL 2008.

NHibernate sekarang tahu bagaimana menghubungkan ke database. Hal lain yang perlu kita lakukan adalah memberikan daftar model yang akan kita petakan.

Kita dapat melakukan ini dengan menambahkan assembly, jadi dengan menentukan file Assembly.GetExecutingAssemblydan di sinilah program akan menemukan file pemetaan. File pemetaan memberi tahu NHibernate cara beralih dari kelas C # ke tabel database.

SessionFactory mengumpulkan semua metadata yang diperlukan untuk menginisialisasi NHibernate. SessionFactory dapat digunakan untuk membuat sesi, yang secara kasar dapat dianalogikan dengan koneksi database. Jadi cara yang tepat adalah dengan menggunakannya di blok using. Bisa saya katakanvar session sama sessionFactory.OpenSession dan saya ingin melakukan ini di dalam transaksinya.

Setelah sesi dibuka, kita dapat memberi tahu sesi untuk memulai transaksi baru dan kemudian kita dapat melakukan beberapa logika di sini. Jadi lakukan beberapa logika database dan akhirnya lakukan transaksi itu.

Dalam bab ini, kami akan membahas beberapa basic mappingdan Anda tahu bahwa dari bab terakhir kita memiliki tabel database serta definisi kelas C #. Kami sekarang membutuhkan pemetaan yang menjelaskan bagaimana menerjemahkan dari C # ke database dan kembali lagi.

Jadi mari kita lanjutkan dan tambahkan file XML baru dengan mengklik kanan pada proyek di explorer solusi dan pilih Add → New Item ...

Memasukkan Student.hbm.xmldi bidang nama. Kami perlu menentukan rakitan default yang akan menjadiNHibernateDemoAppdan juga menentukan namespace default. Ini hanya mempersingkat banyak definisi tipe lain yang akan kita buat dalam file ini.

Berikut adalah implementasinya dalam file XML -

<?xml version = "1.0" encoding = "utf-8" ?> 

<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" 
   assembly = "NHibernateDemoApp" namespace = "NHibernateDemoApp">

   <class name = "Student"> 
      <id name = "ID">
        <generator class = "native"/> 
      </id> 
		
      <property name = "LastName"/> 
      <property name = "FirstMidName"/> 
   </class> 
   
</hibernate-mapping>

Hal berikutnya kita perlu mendefinisikan kelas; kelas ini akan menjadi milik kitaStudent class. Selanjutnya, kita perlu memberi tahu NHibernate nama id, yaitu ID dan saya juga harus memberi tahu NHibernate cara membuat ID, jadi generator kita akan menjadi tipe asli.

Generator tipe asli berarti bahwa dalam database seperti SQL Server, itu akan menggunakan kolom identitas, tipe identitas.

Hal berikutnya yang harus kita lakukan adalah memberi nama properti. Jadi, tambahkan dua properti lagi untuk FirstName, dan LastName.

Sekarang, kami membaca file pemetaan ini dari perakitan. Jadi cara yang disukai untuk melakukan ini adalah dengan memilikinyaHBM filesdimasukkan ke dalam majelis Anda. Kita dapat melakukan ini hanya dengan mengatur properti.

Sekarang klik kanan pada proyek di explorer solusi dan pilih Properties, Anda akan melihat file Build Action field di mana Konten dipilih secara default.

Pilih sumber daya yang disematkan dari daftar tarik-turun.

Jadi ini sebenarnya menyematkan file XML itu di dalam NHibernateDemoApp majelis.

Dalam bab ini, kita akan membahas dasarnya CRUD operations. Sekarang sistem kami siap untuk memulai, karena kami telah berhasil mengimplementasikan domain kelas Student kami, kami juga telah menentukan file pemetaan dan mengkonfigurasi NHibernate. Kami sekarang dapat menggunakan beberapa kueri untuk melakukan operasi CRUD.

Buat Data

Seperti yang Anda lihat bahwa kami tidak memiliki data di tabel Siswa kami di NHibernateDemoDB database.

Jadi untuk menambahkan beberapa data, kita perlu melakukan Add/Create operasi seperti yang ditunjukkan di bawah ini.

using (var session = sefact.OpenSession()) { 

   using (var tx = session.BeginTransaction()) { 
     
      var student1 = new Student { 
         ID = 1, 
         FirstMidName = "Allan", 
         LastName = "Bommer" 
      }; 
      
      var student2 = new Student { 
         ID = 2, 
         FirstMidName = "Jerry", 
         LastName = "Lewis" 
      }; 
      
      session.Save(student1); 
      session.Save(student2); 
      tx.Commit(); 
   } 
   
   Console.ReadLine(); 
}

Seperti yang Anda lihat bahwa kami telah membuat dua siswa dan kemudian memanggil metode Save () dari OpenSession dan kemudian memanggil Commit () dari BeginTransaction. Berikut implementasi lengkapnya diProgram.cs mengajukan

using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Driver; 

using System; 
using System.Linq; 
using System.Reflection;

namespace NHibernateDemoApp { 
   
   class Program { 
      
      static void Main(string[] args) { 
         var cfg = new Configuration();
			
         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;
			
         cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + 
            Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
            TrustServerCertificate + ApplicationIntent + MultiSubnetFailover"; 

            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
         }); 
   
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         var sefact = cfg.BuildSessionFactory(); 
			
         using (var session = sefact.OpenSession()) { 
			
            using (var tx = session.BeginTransaction()) { 
               
               var student1 = new Student { 
                  ID = 1,  
                  FirstMidName = "Allan", 
                  LastName = "Bommer" 
               }; 

               var student2 = new Student { 
                  ID = 2, 
                  FirstMidName = "Jerry", 
                  LastName = "Lewis" 
               }; 
            
               session.Save(student1); 
               session.Save(student2); 
               tx.Commit();
            } 
            
            Console.ReadLine(); 
         } 
      } 
   } 
}

Sekarang mari kita jalankan aplikasi ini dan kemudian pergi ke SQL Server Object Explorer dan refresh database Anda. Anda akan melihat bahwa dua siswa di atas sekarang ditambahkan ke tabel Siswa di database NHibernateDemoDB.

Membaca Data dari Tabel Siswa

Anda dapat melihat bahwa sekarang kami memiliki dua catatan di tabel siswa kami. Untuk membaca record ini dari tabel, kita perlu memanggilCreateCriteria() dari OpenSession seperti yang ditunjukkan pada kode berikut.

using (var session = sefact.OpenSession()) { 
   
   using (var tx = session.BeginTransaction()) { 
      var students = session.CreateCriteria<Student>().List<Student>(); 
      
      foreach (var student in students) { 
         Console.WriteLine("{0} \t{1} \t{2}", 
            student.ID,student.FirstMidName, student.LastName); 
      } 
      
      tx.Commit(); 
   } 
   
   Console.ReadLine(); 
}

Jadi jika Anda menginginkan daftar record maka kita cukup mengatakan daftar tipe Student.

Sekarang gunakan foreach melalui semua siswa dan katakan cetak ID, FirstMidName dan LastNamedi konsol. Sekarang, mari kita jalankan aplikasi ini lagi dan Anda akan melihat output berikut di jendela konsol.

1 Allan Bommer
2 Jerry Lewis

Anda juga dapat mengambil rekaman apa pun dengan menentukan ID di Get() metode OpenSession menggunakan kode berikut.

using (var session = sefact.OpenSession()) { 
   
   using (var tx = session.BeginTransaction()) { 
      var students = session.CreateCriteria<Student>().List<Student>(); 
      
      foreach (var student in students) { 
         Console.WriteLine("{0} \t{1} \t{2}", student.ID, 
            student.FirstMidName, student.LastName); 
      }
      
      var stdnt = session.Get<Student>(1); 
      Console.WriteLine("Retrieved by ID"); 
      Console.WriteLine("{0} \t{1} \t{2}", stdnt.ID, 
         stdnt.FirstMidName, stdnt.LastName); 
      tx.Commit();
   } 
	
   Console.ReadLine(); 
}

Sekarang ketika Anda menjalankan aplikasi Anda, Anda akan melihat output berikut.

1 Allan Bommer
2 Jerry Lewis
Retrieved by ID
1 Allan Bommer

Perbarui Record

Untuk memperbarui record dalam tabel, pertama-tama kita perlu mengambil record tertentu dan kemudian mengupdate record itu dengan memanggil Update() metode OpenSession seperti yang ditunjukkan pada kode berikut.

using (var session = sefact.OpenSession()) { 

   using (var tx = session.BeginTransaction()) { 
      var students = session.CreateCriteria<Student>().List<Student>(); 
     
      foreach (var student in students) { 
         Console.WriteLine("{0} \t{1} \t{2}", student.ID, 
            student.FirstMidName, student.LastName); 
      }
      
      var stdnt = session.Get<Student>(1); 
      Console.WriteLine("Retrieved by ID"); 
      Console.WriteLine("{0} \t{1} \t{2}", stdnt.ID, stdnt.FirstMidName, stdnt.LastName);
      
      Console.WriteLine("Update the last name of ID = {0}", stdnt.ID); 
      stdnt.LastName = "Donald"; 
      session.Update(stdnt); 
      Console.WriteLine("\nFetch the complete list again\n"); 
      
      foreach (var student in students) { 
         Console.WriteLine("{0} \t{1} \t{2}", student.ID, 
            student.FirstMidName, student.LastName); 
      } 
      
      tx.Commit();
   } 
   
   Console.ReadLine();
}

Sekarang ketika Anda menjalankan aplikasi Anda, Anda akan melihat output berikut.

1 Allan Bommer
2 Jerry Lewis
Retrieved by ID
1 Allan Bommer
Update the last name of ID = 1
Fetch the complete list again
1 Allan Donald
2 Jerry Lewis

Seperti yang Anda lihat, Nama Belakang dari ID sama dengan 1 diperbarui dari Bommer ke Donald.

Hapus Rekam

Untuk menghapus rekaman apa pun dari tabel, pertama-tama kita harus mengambil rekaman itu dan kemudian menghapusnya dengan memanggil Delete() metode OpenSession seperti yang ditunjukkan pada kode berikut.

using (var session = sefact.OpenSession()) { 
   
   using (var tx = session.BeginTransaction()) { 
      var students = session.CreateCriteria<Student>().List<Student>();
      
      foreach (var student in students) { 
         Console.WriteLine("{0} \t{1} \t{2}", student.ID, 
            student.FirstMidName, student.LastName); 
      }
      
      var stdnt = session.Get<Student>(1); 
      Console.WriteLine("Retrieved by ID"); 
      Console.WriteLine("{0} \t{1} \t{2}", stdnt.ID, stdnt.FirstMidName, stdnt.LastName);
      
      Console.WriteLine("Delete the record which has ID = {0}", stdnt.ID); 
      session.Delete(stdnt);
      Console.WriteLine("\nFetch the complete list again\n"); 
      
      foreach (var student in students) { 
         Console.WriteLine("{0} \t{1} \t{2}", student.ID, student.FirstMidName, 
            student.LastName); 
      } 
      
      tx.Commit();
   } 
	
   Console.ReadLine(); 
}

Sekarang ketika Anda menjalankan aplikasi Anda, Anda akan melihat output berikut.

1 Allan Donald
2 Jerry Lewis
Retrieved by ID
1 Allan Bommer
Delete the record which has ID = 1
Fetch the complete list again
2 Jerry Lewis

Seperti yang Anda lihat, record yang memiliki ID sama dengan 1 tidak lagi tersedia di database. Anda juga dapat melihat database di SQL Server Object Explorer.

Pada bab ini, kita akan memahami bagaimana semua record dari database itu retrieved, updated, created, and deleted dan bagaimana tepatnya kueri ini dilakukan?

Untuk memahami semua ini, kita cukup menambahkan opsi ke dalam konfigurasi kita, yang mencatat SQL di konsol. Berikut adalah pernyataan sederhana yang akan mencatat kueri SQL -

x.LogSqlInConsole = true;

Sekarang, kami memiliki dua catatan di tabel siswa kami di database NHibernateDemoDB. Mari ambil semua record dari database seperti yang ditunjukkan pada kode berikut.

using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Driver; 

using System; 
using System.Linq; 
using System.Reflection;

namespace NHibernateDemoApp { 

   class Program { 
      
      static void Main(string[] args) { 
         var cfg = new Configuration();
			
         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;			
         
         cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + 
            Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
            TrustServerCertificate + ApplicationIntent + MultiSubnetFailover"; 
            
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.LogSqlInConsole = true; 
         }); 
      
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         var sefact = cfg.BuildSessionFactory();
      
         using (var session = sefact.OpenSession()) { 
         
            using (var tx = session.BeginTransaction()) { 
               Console.WriteLine("\nFetch the complete list again\n");
               var students = session.CreateCriteria<Student>().List<Student>(); 
      
               foreach (var student in students) { 
                  Console.WriteLine("{0} \t{1} \t{2}", student.ID, student.FirstMidName,
                     student.LastName); 
               } 
               
               tx.Commit(); 
            } 
				
            Console.ReadLine(); 
         } 
      } 
   } 
}

Jadi mari kita lanjutkan dan jalankan aplikasi ini lagi, dan Anda akan melihat output berikut -

NHibernate: SELECT this_.ID as ID0_0_, this_.LastName as LastName0_0_,
   this_.FirstMidName as FirstMid3_0_0_ FROM Student this_

Fetch the complete list again

3 Allan Bommer
4 Jerry Lewis

Seperti yang Anda lihat, file select clausesedang dikirim ke database, itu sebenarnya seperti klausa yang akan mengambil ID, FirstMidName dan LastName. Jadi semua ini dikirim ke database dan diproses di sana daripada harus membawa banyak catatan kembali ke server Anda dan diproses di sisi server.

Profiler NHibernate

Cara lain untuk melihat hasil ini adalah dengan menggunakan NHibernate Profiler. NHibernate Profiler adalah alat komersial, tetapi sangat berguna untuk bekerja dengan aplikasi NHibernate. Anda dapat dengan mudah menginstal NHibernate Profiler ke dalam aplikasi Anda dari NuGet.

Pergi ke konsol NuGet Manager dari menu Tools dengan memilih NuGet Package Manager → Package Manager Console. Ini akan membuka jendela Package Manager Console. Masukkan perintah berikut dan tekan enter.

PM> install-package NHibernateProfiler

Ini akan menginstal semua biner yang diperlukan untuk Profiler NHibernate, setelah berhasil diinstal Anda akan melihat pesan berikut.

Anda juga akan melihat bahwa Profiler NHibernate diluncurkan, setelah diinstal. Diperlukan lisensi untuk menggunakannya, tetapi untuk tujuan demo, kami dapat menggunakan versi uji coba NHibernate Profiler selama 30 hari.

Sekarang, Profiler NHibernate dioptimalkan untuk bekerja dengan aplikasi web dan Anda akan melihat bahwa itu telah ditambahkan App_Start folderdi penelusur solusi. Untuk menjaga semua ini tetap sederhana, hapus folder App_Start dan Anda juga akan melihat bahwa satu pernyataan ditambahkan pada awal metode Utama di kelas Program.

App_Start.NHibernateProfilerBootstrapper.PreStart();

Hapus pernyataan ini juga dan tambahkan panggilan sederhana NHibernateProfiler.Initialize seperti yang ditunjukkan pada kode berikut.

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Driver; 

using System; 
using System.Linq; 
using System.Reflection;

namespace NHibernateDemoApp { 
   
   class Program { 
	
      static void Main(string[] args) { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration();
			
         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;			
         
         cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + 
            Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
            TrustServerCertificate + ApplicationIntent + MultiSubnetFailover";
				
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.LogSqlInConsole = true; 
         }); 

         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         var sefact = cfg.BuildSessionFactory(); 
         
         using (var session = sefact.OpenSession()) { 
            
            using (var tx = session.BeginTransaction()){ 
               var students = session.CreateCriteria<Student>().List<Student>(); 
               Console.WriteLine("\nFetch the complete list again\n");
               
               foreach (var student in students) { 
                  Console.WriteLine("{0} \t{1} \t{2}", student.ID, student.FirstMidName,
                     student.LastName); 
               } 
					
               tx.Commit(); 
            } 
				
            Console.ReadLine(); 
         } 
      } 
   
   }
}

Sekarang ketika Anda menjalankan aplikasi, itu akan mengirim data ke aplikasi Profiler NHibernate.

Anda dapat melihat di sini, kami memiliki tampilan bagus yang menunjukkan bahwa kami telah memulai transaksi, apa yang dilakukan SQL ke database dalam format yang bagus.

Jadi ini sangat berguna untuk menentukan apa yang sebenarnya terjadi di dalam aplikasi NHibernate Anda. Ini menjadi sangat berguna setelah aplikasi mencapai tingkat kerumitan tertentu, di mana Anda membutuhkan sesuatu yang lebih seperti SQL Profiler, tetapi dengan pengetahuan tentang NHibernate.

Dalam bab ini, kami akan menambahkan IntelliSense ke file pemetaan NHibernate kami (*.hbm.xml files). Seperti yang Anda amati saat memetakan kelas siswa domain yang saat ini kami tidak memiliki IntelliSense. Sangat berguna untuk memilikiXML schemastersedia. Jadi di bab ini Anda akan memahami cara menambahkan IntelliSense di Visual Studio untuk file XML NHibernate ini.

Buka file pemetaan dan Anda akan melihat bahwa opsi menu XML muncul di menu utama.

Pilih opsi menu XML → Schemas… dan itu akan menampilkan kotak dialog XML Schemas.

Pilih tombol Add… yang ada di kanan atas kotak dialog, yang membuka dialog file. Sekarang pergi kepackages folder, yang ada di folder Solusi proyek Anda dan Anda akan melihat berbagai paket yang disertakan dalam proyek Anda.

Sekarang, klik dua kali NHibernate.4.*** folder dan Anda akan melihat dua file skema (* .xsd) atau file definisi skema XML yang menentukan konfigurasi dan pemetaan NHibernate.

Pilih dua file skema ini dan klik tombol Buka.

Anda dapat melihat bahwa skema NHibernate ditambahkan ke dalam dialog XML Schemas. Klik tombol OK. Sekarang, mari kita mulai tag properti baru dan Anda akan melihat bahwa kami memiliki IntelliSense lengkap di sini.

IntelliSense sekarang tersedia untuk Anda yang menghemat banyak waktu selama pemetaan relasional objek.

Dalam bab ini, kita akan membahas tipe data pemetaan. Memetakan entitas sangat mudah, kelas entitas selalu dipetakan ke tabel database menggunakan<class>, <subclass>, and <joined-subclass>elemen pemetaan. Tipe nilai membutuhkan sesuatu yang lebih, dimana tipe pemetaan dibutuhkan.

NHibernate mampu memetakan berbagai jenis data. Berikut adalah daftar tipe data paling umum yang didukung.

Jenis pemetaan Tipe .NET System.Data.DbType
Int16 System.Int16 DbType.Int16
Int32 System.Int32 DbType.Int32
Int64 System.Int64 DbType.Int64
Tunggal System.Single DbType.Single
Dua kali lipat Sistem. Ganda DbType.Double
Desimal Sistem Desimal DbType.Decimal
Tali System.String DbType.String
AnsiString System.String DbType.AnsiString
Byte System.Byte DbType.Byte
Arang System.Char DbType.StringFixedLength — satu karakter
AnsiChar System.Char DbType.AnsiStringFixedLength — satu karakter
Boolean System.Boolean DbType.Boolean
Guid System.Guid DbType.Guid
PersistentEnum System.Enum (enumerasi) DbType untuk nilai yang mendasari
Benar salah System.Boolean DbType.AnsiStringFixedLength — baik 'T' atau 'F'
Ya Tidak System.Boolean DbType.AnsiStringFixedLength — baik 'Y' atau 'N'
Tanggal Waktu Tanggal Waktu DbType.DateTime — mengabaikan milidetik
Kutu System.DateTime DbType.Int64
Rentang waktu System.TimeSpan DbType.Int64
Stempel waktu System.DateTime DbType.DateTime — sespesifik yang didukung database
Biner System.Byte [] DbType.Binary
BinaryBlob System.Byte [] DbType.Binary
StringClob System.String DbType.String
Dapat diserialkan Setiap System.Object ditandai dengan SerializableAttribute DbType.Binary
CultureInfo System.Globalization.CultureInfo DbType.String — lima karakter untuk budaya
Tipe Tipe sistem DbType.String memegang Assembly Qualified Name

Tabel yang diberikan di atas menjelaskan secara rinci petunjuk yang disebutkan di bawah ini.

  • Semuanya, mulai dari tipe numerik sederhana hingga string, yang dapat dipetakan dalam berbagai cara menggunakan varchars, chars dll serta gumpalan string dan semua jenis yang didukung database.

  • Itu juga bisa memetakan Booleans, baik untuk bidang yang menggunakan nol dan satu, bidang karakter yang berisi benar, salah atau T dan F.

  • Ada berbagai cara untuk menentukan bagaimana peta itu ke ujung belakang, nilai-nilai boolean dalam database.

  • Kami dapat menangani pemetaan DateTime, baik termasuk dan tidak termasuk offset zona waktu, waktu musim panas, dll.

  • Kami juga bisa memetakan enumerations; kita bisa memetakannya ke string atau ke nilai numerik yang mendasarinya.

Mari kita lihat contoh sederhana di mana kita memiliki nama properti yang sama baik di database maupun di kelas Student.

Sekarang mari kita ubah FirstMidName menjadi FirstName di kelas siswa, di mana kita tidak akan mengubah kolom FirstMidName, tapi kita akan melihat bagaimana memberi tahu NHibernate untuk melakukan konversi ini. Berikut adalah kelas siswa yang diperbarui.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks;

namespace NHibernateDemoApp { 
  
   class Student { 
      public virtual int ID { get; set; } 
      public virtual string LastName { get; set; } 
      public virtual string FirstName { get; set; } 
   }
}

Berikut adalah implementasi file pemetaan NHibernate.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemoApp" 
   namespace = "NHibernateDemoApp"> 
   
   <class name = "Student">
	
      <id name = "ID"> 
         <generator class = "native"/>
      </id> 
   
      <property name = "LastName"/> 
      <property name = "FirstName" column = "FirstMidName" type = "String"/> 
   </class> 

</hibernate-mapping>

Dalam contoh ini, asumsikan bahwa bidang FirstName adalah string .NET, dan kolom FirstMidName adalah SQL nvarchar. Sekarang untuk memberi tahu NHibernate bagaimana melakukan konversi ini, setel nama sama denganFirstName dan kolom sama dengan FirstMidName dan tentukan jenis pemetaan yang sama dengan String, yang sesuai untuk konversi khusus ini.

Berikut ini adalah a Program.cs implementasi file.

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Driver; 

using System; 
using System.Linq; 
using System.Reflection;

namespace NHibernateDemoApp { 

   class Program { 
	
      static void Main(string[] args) { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
			
         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;
         
         cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + 
            Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
            TrustServerCertificate + ApplicationIntent + MultiSubnetFailover"; 
            
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.LogSqlInConsole = true; 
         }); 
         
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         var sefact = cfg.BuildSessionFactory();
			
         using (var session = sefact.OpenSession()) { 
            
            using (var tx = session.BeginTransaction()) { 
               var students = session.CreateCriteria<Student>().List<Student>(); 
               Console.WriteLine("\nFetch the complete list again\n"); 
               
               foreach (var student in students) { 
                  Console.WriteLine("{0} \t{1} \t{2}", student.ID, student.FirstName,
                     student.LastName); 
               } 
					
               tx.Commit(); 
            } 
				
            Console.ReadLine(); 
         } 
      } 
   }
}

Sekarang ketika Anda menjalankan aplikasi Anda, Anda akan melihat output berikut.

NHibernate: SELECT this_.ID as ID0_0_, this_.LastName as LastName0_0_, 
   this_.FirstMidName as FirstMid3_0_0_ FROM Student this_

Fetch the complete list again
3 Allan Bommer
4 Jerry Lewis

Seperti yang Anda lihat bahwa itu telah memetakan nama properti yang berbeda ke nama kolom dalam database.

Mari kita lihat contoh lain di mana kita akan menambahkan properti lain di kelas Student enumTipe. Berikut adalah implementasi kelas siswa.

using System; 
using System.Collections.Generic; 
using System.Linq; using System.Text; 
using System.Threading.Tasks; 

namespace NHibernateDemoApp { 
   
   class Student { 
      public virtual int ID { get; set; } 
      public virtual string LastName { get; set; } 
      public virtual string FirstName { get; set; } 
      public virtual StudentAcademicStanding AcademicStanding { get; set; } 
   } 
   
   public enum StudentAcademicStanding { 
      Excellent, 
      Good, 
      Fair, 
      Poor, 
      Terrible 
   } 
}

Seperti yang Anda lihat, pencacahan memiliki berbagai nilai berbeda yang mungkin dimilikinya seperti, Sangat Baik, Baik, Sedang, Buruk dan Buruk.

Melompat ke file pemetaan, Anda dapat melihat bahwa setiap properti ini terdaftar di file pemetaan termasuk yang baru ditambahkan AcademicStanding Properti.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" 
   assembly = "NHibernateDemoApp" namespace = "NHibernateDemoApp"> 
   
   <class name = "Student"> 
	
      <id name = "ID"> 
         <generator class = "native"/> 
      </id> 

      <property name = "LastName"/> 
      <property name = "FirstName" column = "FirstMidName" type = "String"/> 
      <property name = "AcademicStanding"/> 
   </class>  

</hibernate-mapping>

Sekarang kita juga perlu mengubah database, jadi pergi ke SQL Server Object Explorer dan klik kanan pada database dan pilih opsi New Query….

Ini akan membuka editor kueri dan kemudian menentukan kueri di bawah ini.

DROP TABLE [dbo].[Student]

CREATE TABLE [dbo].[Student] ( 
   [ID] INT IDENTITY (1, 1) NOT NULL, 
   [LastName] NVARCHAR (MAX) NULL, 
   [FirstMidName] NVARCHAR (MAX) NULL, 
   [AcademicStanding] NCHAR(10) NULL, 
   CONSTRAINT [PK_dbo.Student] PRIMARY KEY CLUSTERED ([ID] ASC) 
);

Kueri ini pertama-tama akan menjatuhkan tabel siswa yang ada dan kemudian membuat tabel baru.

Klik ikon Execute seperti yang ditunjukkan di atas. Setelah query berhasil dijalankan maka Anda akan melihat pesan.

Perluas database dan dropdown Tabel, lalu klik kanan pada tabel Siswa dan pilih Lihat Desainer.

Sekarang, Anda akan melihat tabel yang baru dibuat, yang juga memiliki properti baru AcademicStanding.

Mari tambahkan dua record seperti yang ditunjukkan berikut ini Program.cs mengajukan.

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Driver; 

using System; 
using System.Linq; 
using System.Reflection;

namespace NHibernateDemoApp { 

   class Program { 
      
      static void Main(string[] args) { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
			
         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;
         
         cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + 
            Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
            TrustServerCertificate + ApplicationIntent + MultiSubnetFailover"; 
            
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
         }); 
         
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         var sefact = cfg.BuildSessionFactory(); 
         
         using (var session = sefact.OpenSession()) { 
            using (var tx = session.BeginTransaction()) { 
               
               var student1 = new Student { 
                  ID = 1, 
                  FirstName = "Allan", 
                  LastName = "Bommer",
                  AcademicStanding = StudentAcademicStanding.Excellent 
               };
               
               var student2 = new Student { 
                  ID = 2, 
                  FirstName = "Jerry", 
                  LastName = "Lewis", 
                  AcademicStanding = StudentAcademicStanding.Good 
               };
					
               session.Save(student1); 
               session.Save(student2);
               var students = session.CreateCriteria<Student>().List<Student>(); 
               Console.WriteLine("\nFetch the complete list again\n");
               
               foreach (var student in students) { 
                  Console.WriteLine("{0} \t{1} \t{2} \t{3}", student.ID,
                     student.FirstName, student.LastName, student.AcademicStanding); 
               } 
					
               tx.Commit(); 
            }
				
            Console.ReadLine(); 
         } 
      } 
   } 
}

Sekarang mari jalankan aplikasi Anda dan Anda akan melihat output berikut di jendela konsol Anda.

Fetch the complete list again

1 Allan Bommer Excellent
2 Jerry Lewis Good

Sekarang mari kita lihat database dengan mengklik kanan pada Tabel Siswa.

Pilih Lihat Data dan Anda akan melihat dua catatan di tabel siswa seperti yang ditunjukkan pada gambar layar berikut.

Anda dapat melihat bahwa dua record ditambahkan dan Allan memiliki AcademicStanding 0 dan Jerry memiliki AcademicStanding 1. Ini karena dalam .Net nilai pencacahan pertama secara default memiliki 0, yang merupakan Excellent jika Anda melihat StudentAcademicStanding. Sedangkan pada file Student.cs Good adalah yang kedua, sehingga memiliki nilai 1.

Dalam bab ini, kita akan melihat konfigurasi NHibernate. Kami memiliki cara berbeda untuk mengkonfigurasi NHibernate. Ini terbagi menjadi dua kelompok utama

  • Konfigurasi berbasis XML
  • Konfigurasi berbasis kode

Konfigurasi Berbasis Kode

Konfigurasi berbasis kode dibangun ke dalam NHibernate. Itu diperkenalkan di sekitar NHibernate 3 dan kami telah menggunakan konfigurasi basis kode hingga sekarang.

String Data Source = asia13797\\sqlexpress;
String Initial Catalog = NHibernateDemoDB;
String Integrated Security = True;
String Connect Timeout = 15;
String Encrypt = False;
String TrustServerCertificate = False;
String ApplicationIntent = ReadWrite;
String MultiSubnetFailover = False;

cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + 
   Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
   TrustServerCertificate + ApplicationIntent + MultiSubnetFailover"; 
   
   x.Driver<SqlClientDriver>(); 
   x.Dialect<MsSql2008Dialect>(); 
   x.LogSqlInConsole = true; 
}); 

cfg.AddAssembly(Assembly.GetExecutingAssembly());

Semua konfigurasi ditentukan dalam kode C #. Anda dapat melihat di sini bahwa kami telah mendapatkan objek konfigurasi baru kami, dan kemudian kami gunakanloquacious configurationyang diperkenalkan dengan NHibernate 3.1 untuk mengkonfigurasi database. String koneksi apa yang kami gunakan, database apa yang kami hubungkan dan dialek yang akan digunakan. Kami juga menambahkan perakitan pemetaan kami langsung ke sini.

Konfigurasi Berbasis XML

Jika Anda menggunakan konfigurasi berbasis XML, Anda dapat menggunakan file hibernate.cfg.xml file, yang hanya merupakan file xml mandiri menggunakan skema NHibernate, atau Anda dapat menyematkan konfigurasi khusus NHibernate di dalam aplikasi Anda atau web.cfg. Nama hibernate.cfg.xml secara default, tetapi kita dapat menggunakan nama arbitrer untuk file xml itu juga.

Mari kita lihat konfigurasi berbasis XML dengan menambahkan file xml baru ke proyek NHibernateDemoApp dan menyebutnya hibernate.cfg.xml.

Masukkan informasi berikut ke dalam file hibernate.cfg.xml.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-configuration xmlns = "urn:nhibernate-configuration-2.2"> 
   <session-factory> 
   
      <property name = "connection.connection_string">
         Data Source = asia13797\\sqlexpress;
         Initial Catalog = NHibernateDemoDB;
         Integrated Security = True;
         Connect Timeout = 15;
         Encrypt = False;
         TrustServerCertificate = False;
         ApplicationIntent = ReadWrite;
         MultiSubnetFailover = False;
      </property> 
      
      <property name = "connection.driver_class">
         NHibernate.Driver.SqlClientDriver
      </property> 
		
      <property name = "dialect">
         NHibernate.Dialect.MsSql2008Dialect
      </property> 
		
      <mapping assembly = "NHibernateDemoApp"/>
		
   </session-factory> 
	
</hibernate-configuration>

Seperti yang Anda lihat pada file xml di atas, kami telah menetapkan konfigurasi yang sama seperti yang disebutkan di C #.

Sekarang mari mengomentari konfigurasi ini dari file Program.cs dan panggil saja Configure() metode, yang akan memuat file hibernate.cfg.xml file seperti yang ditunjukkan di bawah ini.

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Driver; 

using System; 
using System.Linq; 
using System.Reflection; 

namespace NHibernateDemoApp { 

   class Program { 
      
      static void Main(string[] args) { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         //cfg.DataBaseIntegration(x =>
         
         //{ 
            // x.ConnectionString = "Data Source = asia13797;\\sqlexpress
            Initial Catalog = NHibernateDemoDB;
            Integrated Security = True;
            Connect Timeout = 15;
            Encrypt =False;
            TrustServerCertificate = False;
            ApplicationIntent = ReadWrite;
            MultiSubnetFailover = False"; 
            
            // x.Driver<SqlClientDriver>(); 
            // x.Dialect<MsSql2008Dialect>(); 
            // x.LogSqlInConsole = true; 
         //}); 
         
         //cfg.AddAssembly(Assembly.GetExecutingAssembly());
         cfg.Configure();
         var sefact = cfg.BuildSessionFactory();
			
         using (var session = sefact.OpenSession()) { 
            
            using (var tx = session.BeginTransaction()) { 
               var students = session.CreateCriteria<Student>().List<Student>(); 
               Console.WriteLine("\nFetch the complete list again\n"); 
               
               foreach (var student in students) { 
                  Console.WriteLine("{0} \t{1} \t{2} \t{3}", student.ID,
                     student.FirstName, student.LastName, student.AcademicStanding); 
               } 
					
               tx.Commit(); 
            } 
				
            Console.ReadLine(); 
         } 
      } 
   } 
}

Jalankan aplikasi Anda lagi dan Anda akan melihat output yang sama.

Fetch the complete list again

1 Allan Bommer Excellent
2 Jerry Lewis Good

Dalam bab ini, kami akan membahas cara mengganti konfigurasi NHibernate. Ada beberapa hal yang perlu Anda ingat.

  • Pertama-tama, konfigurasi di NHibernate adalah aditif.

  • Jadi, Anda tidak hanya harus menggunakan satu file xml atau Anda tidak hanya harus menggunakan konfigurasi berbasis kode atau NHibernate yang lancar.

  • Anda dapat mencampur dan mencocokkan semua metode ini tergantung pada bagaimana Anda ingin mengkonfigurasi aplikasi Anda.

  • Hal penting yang perlu diingat adalah, terakhir konfigurasi menang.

Dalam contoh berikut, Anda dapat melihat bahwa kita membuat objek konfigurasi kita, mengkonfigurasinya menggunakan konfigurasi berbasis kode dan terakhir memanggil cfg.configure() metode, yang memuat file hibernate.cfg.xml.

String Data Source = asia13797\\sqlexpress;
String Initial Catalog = NHibernateDemoDB;
String Integrated Security = True;
String Connect Timeout = 15;
String Encrypt = False;
String TrustServerCertificate = False;
String ApplicationIntent = ReadWrite;
String MultiSubnetFailover = False;

cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + 
   Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
   TrustServerCertificate + ApplicationIntent + MultiSubnetFailover"; 
	
   x.Driver<SqlClientDriver>(); 
   x.Dialect<MsSql2008Dialect>(); 
   x.LogSqlInConsole = true; 
}); 

cfg.Configure();
  • Jadi apa pun di dalam hibernate.cfg.xml menimpa pengaturan yang ditetapkan oleh konfigurasi berbasis kode.

  • Dengan membalikkan kedua proses ini, kita dapat memiliki default di dalam hibernate.cfg.xml dan kemudian melakukan penggantian di dalam konfigurasi berbasis kode.

  • Tidak ada yang dikecualikan jika Anda menggunakan konfigurasi berbasis kode dan juga tidak ada yang mencegah Anda menggunakan file hibernate.cfg.xml.

Mari kita lihat contoh sederhana di mana kita akan mengganti konfigurasi dengan menggunakan campuran konfigurasi berbasis xml dan berbasis kode.

Mari kita juga memindahkan string koneksi ke app.config file menggunakan kode berikut.

<?xml version = "1.0" encoding = "utf-8" ?> 

<configuration> 
   
   <startup> 
      <supportedRuntime version = "v4.0" sku = ".NETFramework,Version = v4.5" /> 
   </startup> 
   
   <connectionStrings> 
      <add name = "default" connectionString = "Data Source =
         asia13797\\sqlexpress;
         Initial Catalog = NHibernateDemoDB;
         Integrated Security = True;
         Connect Timeout = 15;
         Encrypt = False;
         TrustServerCertificate = False;
         ApplicationIntent = ReadWrite;
         MultiSubnetFailover = False"/> 
   </connectionStrings> 

</configuration>

String koneksi ada di beberapa app.configfile dengan nama default. Sekarang, kita perlu menyebutkan nama default di file hibernate.cfg.xml alih-alih string koneksi.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-configuration xmlns = "urn:nhibernate-configuration-2.2"> 

   <session-factory> 
      <property name = "connection.connection_string">default</property> 
		
      <property name = "connection.driver_class">
         NHibernate.Driver.SqlClientDriver
      </property> 
		
      <property name = "dialect">
         NHibernate.Dialect.MsSql2008Dialect
      </property> 
		
      <mapping assembly = "NHibernateDemoApp"/> 
   </session-factory> 

</hibernate-configuration>

Mari mengomentari bagian string koneksi, driver, dan bagian dialek dari konfigurasi berbasis kode, karena program akan membacanya dari file hibernate.cfg.xml dan LogSqlInConsole bagian akan tetap dalam konfigurasi berbasis kode.

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Driver; 

using System; 
using System.Linq; 
using System.Reflection;
namespace NHibernateDemoApp { 
   
   class Program { 
	
      static void Main(string[] args) { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration();
			
         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;
			
         cfg.DataBaseIntegration(x = > { //x.ConnectionString = "Data Source + 
            Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
            TrustServerCertificate + ApplicationIntent + MultiSubnetFailover";
				
            //x.Driver<SqlClientDriver>(); 
            //x.Dialect<MsSql2008Dialect>(); 
            x.LogSqlInConsole = true; 
         }); 
         
         cfg.Configure(); 
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         var sefact = cfg.BuildSessionFactory(); 
			
         using (var session = sefact.OpenSession()) { 
			
            using (var tx = session.BeginTransaction()) { 
               
               var students = session.CreateCriteria<Student>().List<Student>();
               Console.WriteLine("\nFetch the complete list again\n"); 
               
               foreach (var student in students) { 
                  Console.WriteLine("{0} \t{1} \t{2} \t{3}", student.ID,
                  student.FirstName, student.LastName, student.AcademicStanding); 
               } 
					
               tx.Commit(); 
            }
				
            Console.ReadLine(); 
         } 
      } 
   } 
}

Sekarang ketika Anda menjalankan aplikasi, Anda akan melihat bahwa program telah membaca log dari konfigurasi berbasis kode dan konfigurasi lain dari file hibernate.cfg.xml.

NHibernate: SELECT this_.ID as ID0_0_, this_.LastName as LastName0_0_,   
   this_.FirstMidName as FirstMid3_0_0_, this_.AcademicStanding as Academic4_0_0_ FROM
   Student this_

Fetch the complete list again
1 Allan Bommer Excellent
2 Jerry Lewis Good

Jadi sekarang kami memiliki beberapa konfigurasi kami di dalam file hibernate.cfg.xml file, beberapa di antaranya ada di dalam konfigurasi berbasis kode dan tergantung pada urutan panggilan berbasis kode versus configure(), kita dapat mengubah mana yang menimpa yang lain.

Dalam bab ini, kami akan membahas pembaruan ukuran batch. Ukuran batch memungkinkan Andacontrol the number of updates yang keluar dalam satu perjalanan pulang pergi ke database Anda untuk database yang didukung.

  • Ukuran batch pembaruan telah default pada NHibernate 3.2.

  • Tetapi jika Anda menggunakan versi sebelumnya atau perlu menyesuaikan aplikasi NHibernate Anda, Anda harus melihat ukuran kumpulan pembaruan, yang merupakan parameter yang sangat berguna yang dapat digunakan untuk menyesuaikan kinerja NHibernate.

  • Sebenarnya ukuran batch mengontrol berapa banyak sisipan untuk didorong keluar dalam grup ke database.

  • Saat ini, hanya SQL Server dan Oracle yang mendukung opsi ini karena penyedia database yang mendasarinya perlu mendukung pengelompokan kueri.

Mari kita lihat contoh sederhana di mana kita telah mengatur ukuran batch menjadi 10 yang akan memasukkan 10 record dalam satu set.

cfg.DataBaseIntegration(x => { 
  
   x.ConnectionString = "default"; 
   x.Driver<SqlClientDriver>(); 
   x.Dialect<MsSql2008Dialect>(); 
   x.LogSqlInConsole = true; 
   x.BatchSize = 10; 

});

Berikut adalah implementasi lengkap di mana 25 record akan ditambahkan ke database.

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Driver; 

using System; 
using System.Linq; 
using System.Reflection;
namespace NHibernateDemoApp {
   
   class Program {
	
      static void Main(string[] args) { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
			
         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;
			
         cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + 
            Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
            TrustServerCertificate + ApplicationIntent + MultiSubnetFailover";
         
            x.Driver>SqlClientDriver<(); 
            x.Dialect>MsSql2008Dialect>(); 
            x.LogSqlInConsole = true; 
            x.BatchSize = 10; 
         }); 
         
         //cfg.Configure(); 
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         var sefact = cfg.BuildSessionFactory();
			
         using (var session = sefact.OpenSession()) {
			
            using (var tx = session.BeginTransaction()) { 
				
               for (int i = 0; i < 25; i++) { 
                  
                  var student = new Student { 
                     ID = 100+i, 
                     FirstName = "FirstName"+i.ToString(), 
                     LastName = "LastName" + i.ToString(), 
                     AcademicStanding = StudentAcademicStanding.Good 
                  };
						
                  session.Save(student); 
               } 
					
               tx.Commit();
               var students = session.CreateCriteria<Student>().List<Student>(); 
               Console.WriteLine("\nFetch the complete list again\n"); 
               
               foreach (var student in students) { 
                  Console.WriteLine("{0} \t{1} \t{2} \t{3}", student.ID,student.FirstName,
                     student.LastName, student.AcademicStanding); 
               } 
            } 
				
            Console.ReadLine(); 
         } 
      }
   } 
}

Sekarang mari kita jalankan aplikasi Anda dan Anda melihat semua pembaruan tersebut beralih ke profiler NHibernate. Kami memiliki 26 perjalanan pulang pergi individu ke database 25 untuk penyisipan dan satu mengambil daftar siswa.

Nah, mengapa demikian? Alasannya karena NHibernate perlu melakukan aselect scope identity karena kami menggunakan strategi pembuatan pengenal asli dalam file pemetaan untuk ID seperti yang ditunjukkan pada kode berikut.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" 
   assembly = "NHibernateDemoApp" 
   namespace = "NHibernateDemoApp"> 
   
   <class name = "Student"> 

      <id name = "ID"> 
         <generator class = "native"/> 
      </id> 

      <property name = "LastName"/> 
      <property name = "FirstName" column = "FirstMidName" type = "String"/> 
      <property name = "AcademicStanding"/> 
   
   </class> 
</hibernate-mapping>

Jadi kita perlu menggunakan metode yang berbeda seperti guid.combmetode. Jika kita akan pergi ke guid.comb, kita harus pergi ke pelanggan kita dan mengubahnya menjadi aguid. Jadi itu akan bekerja dengan baik. Sekarang mari kita ubah dari native ke guid.comb menggunakan kode berikut.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly =
   "NHibernateDemoApp" namespace = "NHibernateDemoApp"> 
   <class name = "Student"> 

      <id name = "ID"> 
         <generator class = "guid.comb"/> 
      </id> 

      <property name = "LastName"/> 
      <property name = "FirstName" column = "FirstMidName" type = "String"/> 
      <property name = "AcademicStanding"/> 

   </class> 

</hibernate-mapping>

Jadi database yang bertanggung jawab untuk menghasilkan ID tersebut. Satu-satunya cara NHibernate dapat mengetahui ID apa yang dibuat adalah dengan memilihnya segera setelahnya. Atau, jika kita telah membuat sekumpulan siswa, itu tidak akan bisa cocok dengan ID siswa yang telah dibuat.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks;

namespace NHibernateDemoApp { 

   class Student { 
      public virtual Guid ID { get; set; } 
      public virtual string LastName { get; set; } 
      public virtual string FirstName { get; set; } 
      public virtual StudentAcademicStanding AcademicStanding { get; set; }
   } 
	
   public enum StudentAcademicStanding { 
      Excellent, 
      Good, 
      Fair, 
      Poor, 
      Terrible 
   }
}

Kami hanya perlu memperbarui database kami. Mari jatuhkan tabel siswa dan buat tabel baru dengan menentukan kueri berikut, jadi buka SQL Server Object Explorer dan klik kanan pada database dan pilihNew Query… pilihan.

Ini akan membuka editor kueri dan kemudian menentukan kueri berikut.

DROP TABLE [dbo].[Student]
CREATE TABLE [dbo].[Student] ( 

   -- [ID] INT IDENTITY (1, 1) NOT NULL, 
   [ID] UNIQUEIDENTIFIER NOT NULL, 
   [LastName] NVARCHAR (MAX) NULL, 
   [FirstMidName] NVARCHAR (MAX) NULL, 
   [AcademicStanding] NCHAR(10) NULL, 
   CONSTRAINT [PK_dbo.Student] PRIMARY KEY CLUSTERED ([ID] ASC) 
);

Kueri ini pertama-tama akan menjatuhkan tabel siswa yang ada dan kemudian membuat tabel baru. Seperti yang Anda lihat, kami telah menggunakanUNIQUEIDENTIFIER daripada menggunakan kunci primer integer sebagai ID.

Jalankan kueri ini dan kemudian buka Designer view dan Anda akan melihat bahwa sekarang ID dibuat dengan pengenal unik seperti yang ditunjukkan pada gambar berikut.

Sekarang kita perlu menghapus ID dari file program.cs, saat memasukkan data, karena sekarang ini akan menghasilkan guids untuk itu secara otomatis.

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Driver; 

using System; 
using System.Linq; 
using System.Reflection;
namespace NHibernateDemoApp { 
   
   class Program { 
	
      static void Main(string[] args) { 
		
         NHibernateProfiler.Initialize();
         var cfg = new Configuration();

         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;
			
         cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + 
            Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
            TrustServerCertificate + ApplicationIntent + MultiSubnetFailover"; 
				
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.LogSqlInConsole = true;
            x.BatchSize = 10; 
         }); 
         
         //cfg.Configure(); 
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         var sefact = cfg.BuildSessionFactory(); 
			
         using (var session = sefact.OpenSession()) { 
			
            using (var tx = session.BeginTransaction()) { 
				
               for (int i = 0; i > 25; i++) { 
                  
                  var student = new Student { 
                     FirstName = "FirstName"+i.ToString(), 
                     LastName = "LastName" + i.ToString(), 
                     AcademicStanding = StudentAcademicStanding.Good 
                  }; 
                  
                  session.Save(student); 
               } 
					
               tx.Commit(); 
               var students = session.CreateCriteria<Student>().List<Student>(); 
               Console.WriteLine("\nFetch the complete list again\n"); 
               
               foreach (var student in students) { 
                  Console.WriteLine("{0} \t{1} \t{2} \t{3}", student.ID,
                     student.FirstName,student.LastName, student.AcademicStanding);
               } 
            
            }
				
            Console.ReadLine(); 
         } 
      } 
   } 
}

Sekarang jalankan aplikasi lagi dan lihat profiler NHibernate. Sekarang pembuat profil NHibernate daripada membuat 26 perjalanan pulang pergi hanya akan membuat empat.

Ini disisipkan sepuluh baris ke dalam tabel, lalu sepuluh baris lagi, dan kemudian lima baris lainnya. Dan setelah komit, itu telah menyisipkan satu lagi untuk mengambil semua catatan.

  • Jadi itu dibagi menjadi sepuluh kelompok, sebaik mungkin.

  • Jadi, jika Anda melakukan banyak penyisipan, ini dapat secara dramatis meningkatkan kinerja penyisipan dalam aplikasi Anda, karena Anda dapat menumpuknya.

  • Ini karena NHibernate menetapkan sendiri panduan tersebut menggunakan guid.comb algoritma, dan tidak harus bergantung pada database untuk melakukan ini.

  • Jadi, menggunakan ukuran tumpukan adalah cara terbaik untuk menyetelnya.

Dalam bab ini, kami akan membahas bagaimana file cachingbekerja dalam aplikasi NHibernate. Ini memiliki dukungan built-in untuk caching. Ini terlihat sebagai fitur sederhana, tetapi pada kenyataannya, ini adalah salah satu fitur yang paling kompleks. Kami akan mulai dengan Cache Tingkat Pertama.

Cache Tingkat Pertama

Mekanisme cache ini diaktifkan secara default di NHibernate dan kami tidak perlu melakukan apa pun untuk bekerja dengan cache. Untuk memahami ini, mari kita lihat contoh sederhana, seperti yang Anda lihat bahwa kita memiliki dua record dalam database kita.

Sekarang dalam contoh ini, kami akan mengambil siswa yang ID-nya 1 dan kami akan menggunakan kueri sesi yang sama dua kali seperti yang ditunjukkan pada kode berikut.

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cache; 
using NHibernate.Cfg; 
using NHibernate.Dialect;
using NHibernate.Driver; 
using NHibernate.Linq; 

using System; 
using System.Linq; 
using System.Reflection;
namespace NHibernateDemoApp { 
   
   class Program { 
      static void Main(string[] args) {
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
			
         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;
         
         cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + 
            Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
            TrustServerCertificate + ApplicationIntent + MultiSubnetFailover";
				
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.LogSqlInConsole = true; 
            x.BatchSize = 10; 
         }); 
         
         //cfg.Configure(); 
         
         cfg.Cache(c => { 
            c.UseMinimalPuts = true; 
            c.UseQueryCache = true; 
         }); 
			
         cfg.SessionFactory().Caching .Through<HashtableCacheProvider>()
            .WithDefaultExpiration(1440); 
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         var sefact = cfg.BuildSessionFactory(); 
         
         using (var session = sefact.OpenSession()){ 
			
            using (var tx = session.BeginTransaction()) { 
               var studentUsingTheFirstQuery = session.Get<Student>(1);
               var studentUsingTheSecondQuery = session.Get<Student>(1); 
            } 
            
            Console.ReadLine(); 
         } 
      } 
   } 
}

Sekarang mari kita jalankan aplikasi ini dan lihat hasilnya di NHibernate Profiler.

Anda akan terkejut melihat bahwa NHibernate hanya mengaktifkan satu kueri. Beginilah cara NHibernate menggunakan cache tingkat pertama. Ketika query pertama dijalankan, maka NHibernate meng-cache Siswa dengan ID = 1 di cache tingkat pertama.

Jadi, ketika query kedua dieksekusi maka NHibernate pertama-tama mencari cache tingkat pertama. Entitas mahasiswa dengan ID = 1, jika menemukan entitas tersebut, maka NHibernate mengetahui bahwa, tidak perlu mengaktifkan query lain untuk mengambil kembali objek karyawan yang sama. .

Pada bab ini, kita akan berbicara tentang komponen pemetaan. Di NHibernate,component is a value object. Itu tidak memiliki identitasnya sendiri.

  • Contohnya adalah benda uang, dompet atau dompet mungkin berisi uang di dalamnya, tetapi identitas pasti uang itu tidak relevan.

  • Itu tidak memiliki kunci utama sendiri, tetapi komponen itu sendiri tetap ada dalam tabel yang sama dengan objek pemilik.

Mari kita lihat contoh sederhana di mana seorang siswa memiliki Alamat, yang merupakan objek Location class terkait dengannya.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks;

namespace NHibernateDemoApp { 

   class Student { 
      public virtual int ID { get; set; } 
      public virtual string LastName { get; set; } 
      public virtual string FirstName { get; set; } 
      public virtual StudentAcademicStanding AcademicStanding { get; set; } 
      public virtual Location Address { get; set; } 
   }

   public class Location { 
      public virtual string Street { get; set; } 
      public virtual string City { get; set; } 
      public virtual string Province { get; set; } 
      public virtual string Country { get; set; } 
   }
  
   public enum StudentAcademicStanding { 
      Excellent, 
      Good, 
      Fair, 
      Poor, 
      Terrible 
   } 
}

Sekarang, kita juga perlu mengupdate database dengan mengeksekusi query berikut, yang akan menjatuhkan tabel Student terlebih dahulu dan kemudian membuat tabel baru yang juga akan berisi kolom untuk class Location.

DROP TABLE [dbo].[Student]
CREATE TABLE [dbo].[Student] ( 

   [ID] INT IDENTITY (1, 1) NOT NULL, 
   [LastName] NVARCHAR (MAX) NULL, 
   [FirstMidName] NVARCHAR (MAX) NULL, 
   [AcademicStanding] NCHAR(10) NULL, 
   [Street] NVARCHAR (100) NULL, 
   [City] NVARCHAR (100) NULL, 
   [Province] NVARCHAR (100) NULL, 
   [Country] NVARCHAR (100) NULL, 
   CONSTRAINT [PK_dbo.Student] PRIMARY KEY CLUSTERED ([ID] ASC) 

);

Sekarang untuk memetakan kolom-kolom yang tidak secara langsung menjadi bagian dari kelas siswa, tetapi mereka adalah properti kelas Lokasi dan objek kelas Lokasi didefinisikan di kelas siswa. Kami membutuhkan komponen untuk memetakannya dengan benar. Mari buat komponen distudent.hbm.xml file seperti yang ditunjukkan pada kode berikut.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" 
   assembly = "NHibernateDemoApp" namespace = "NHibernateDemoApp"> 

   <class name = "Student"> 
      <id name = "ID"> 
         <generator class = "native"/>
      </id> 
   
      <property name = "LastName"/> 
		
      <property name = "FirstName" column = "FirstMidName" type = "String"/> 
      <property name = "AcademicStanding"/>
      
      <component name = "Address"> 
         <property name = "Street"/> 
         <property name = "City"/> 
         <property name = "Province"/> 
         <property name = "Country"/> 
      </component> 
   
   </class> 
</hibernate-mapping>

Komponen ini adalah Alamat dan memiliki properti berbeda di atasnya. Dengan informasi ini, NHibernate sekarang memiliki cukup banyak informasi sehingga benar-benar dapat memetakannya.

Sekarang di sini adalah file Program.cs di mana objek siswa baru dibuat dan diinisialisasi dan kemudian disimpan ke database. Ini kemudian akan mengambil daftar dari database.

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cache; 
using NHibernate.Caches.SysCache; 
using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Driver; 
using NHibernate.Linq; 

using System; 
using System.Linq; 
using System.Reflection;
namespace NHibernateDemoApp { 

   class Program {
	
      static void Main(string[] args) { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration();

         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;			
         
         cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + 
            Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
            TrustServerCertificate + ApplicationIntent + MultiSubnetFailover";
				
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
         }); 
         
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         var sefact = cfg.BuildSessionFactory(); 
			
         using (var session = sefact.OpenSession()) { 
			
            using (var tx = session.BeginTransaction()) { 
               
               var student1 = new Student { 
                  ID = 1, 
                  FirstName = "Allan", 
                  LastName = "Bommer", 
                  AcademicStanding = StudentAcademicStanding.Poor, 
                  
                  Address = new Location { 
                     Street = "123 Street", 
                     City = "Lahore", 
                     Province = "Punjab", 
                     Country = "Pakistan" 
                  } 
               }; 
					
               session.Save(student1); 
               tx.Commit(); 
               var students = session.Query<Student>().ToList<Student>();
               Console.WriteLine("\nFetch the complete list again\n"); 
               
               foreach (var student in students) { 
                  Console.WriteLine("{0} \t{1} \t{2} \t{3} \t{4} \t{5} \t{6} \t{7}", 
                     student.ID, 
                     student.FirstName, 
                     student.LastName, 
                     student.AcademicStanding, 
                     student.Address.Street, 
                     student.Address.City, 
                     student.Address.Province, 
                     student.Address.Country
                  ); 
               } 
            } 
            Console.ReadLine(); 
         } 
      }
   } 
}

Sekarang kita dapat menjalankan aplikasi ini dan NHibernate dapat menyimpan nilai tersebut ke database. Saat Anda menjalankan aplikasi, Anda akan melihat output berikut.

Fetch the complete list again

2 Allan Bommer Poor 123 Street Lahore Punjab Pakistan

Berikut adalah nilai-nilai dalam database.

Komponen memungkinkan kita untuk memisahkan kolom yang ada di tabel database ke dalam kelasnya sendiri yang terpisah.

  • Hal lain yang perlu diperhatikan di sini adalah karena Lokasi adalah kelas, bukan entitas.

  • Ini adalah objek tipe nilai dan tidak memiliki kunci utama sendiri.

  • Itu disimpan dalam tabel yang sama dengan Siswa yang berisi itu.

  • Itulah mengapa kami menggunakan komponen di sini.

  • Hal ini memungkinkan banyak fleksibilitas untuk mengubah lapisan kelas kita, bagaimana kelas kita didefinisikan versus bagaimana database kita ditata.

Dalam bab ini, kita akan melihat hubungan di NHibernate. Mari kita alihkan perhatian kita pada bagaimana kita dapat memahami hubungan di NHibernate. Cara termudah adalah memikirkan hubungan dari perspektif database.

  • Pertama-tama kita akan membuat aplikasi baru di mana kita akan membuat beberapa hubungan antara pelanggan dan entitas pesanan.

  • Hubungan pertama yang akan kita lihat adalah hubungan koleksi klasik.

  • Kami memiliki pelanggan dengan koleksi pesanan.

  • Ini adalah hubungan satu ke banyak dan diwakili dalam database dengan 2 tabel dan ada ID pelanggan di tabel pesanan dan kami memiliki hubungan kunci asing kembali ke pelanggan.

Pertama kita perlu membuat database dan dua tabel Customer dan Order. Anda dapat membuat ini dengan menentukan kueri berikut di SQL Server Explorer.

USE [master] 
GO 
CREATE DATABASE [NHibernateDemo] 
GO 
USE [NHibernateDemo] 
GO

CREATE TABLE [dbo].[Customer]( 
   [Id] [uniqueidentifier] NOT NULL, 
   [FirstName] [nvarchar](100) NOT NULL, 
   [LastName] [nvarchar](100) NOT NULL, 
   [Points] [int] NULL, [HasGoldStatus] [bit] NULL, 
   [MemberSince] [date] NULL, 
   [CreditRating] [nchar](20) NULL, 
   [AverageRating] [decimal](18, 4) NULL, 
   [Street] [nvarchar](100) NULL, 
   [City] [nvarchar](100) NULL, 
   [Province] [nvarchar](100) NULL, 
   [Country] [nvarchar](100) NULL,
   PRIMARY KEY CLUSTERED ([Id] ASC) 
) 

GO 
CREATE TABLE [dbo].[Order]( 
   [Id] [uniqueidentifier] NOT NULL, 
   [CustomerId] [uniqueidentifier] NULL, 
   [Ordered] [datetime] NULL, 
   [Shipped] [datetime] NULL, 
   [Street] [nvarchar](100) NULL, 
   [City] [nvarchar](100) NULL, 
   [Province] [nvarchar](100) NULL, 
   [Country] [nvarchar](100) NULL, 
   PRIMARY KEY CLUSTERED ([Id] ASC) 
) 
GO

Ini akan membuat dua tabel dalam database. Gambar berikut menunjukkan Tabel Pelanggan.

Gambar berikut menunjukkan Tabel Pesanan di mana Anda dapat melihat hubungan kunci asing kembali ke pelanggan.

Kita perlu mendefinisikan string koneksi di file app.config file, berikut adalah implementasi dari file app.config.

<?xml version = "1.0" encoding = "utf-8" ?> 
<configuration> 
   
   <connectionStrings> 
      <add name = "default" connectionString = "Data Source =
         (localdb)\MSSQLLocalDB;Initial Catalog = NHibernateDemo;Integrated Security =
         True;Connect Timeout = 30;Encrypt = False;TrustServerCertificate = False;
         ApplicationIntent = ReadWrite;MultiSubnetFailover = False"/> 
   </connectionStrings> 

</configuration>

Untuk menginstal NHibernate di aplikasi Anda, jalankan perintah berikut di jendela NuGet Manager Console.

install-package NHibernate

Untuk mengkonfigurasi konfigurasi NHibernate, kita perlu menentukan konfigurasi di hibernate.cfg.xml file seperti yang ditunjukkan pada kode berikut.

<xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-configuration xmlns = "urn:nhibernate-configuration-2.2"> 
   
   <session-factory> 
      <property name = "connection.connection_string_name">default</property>
		
      <property name = "connection.driver_class">
         NHibernate.Driver.SqlClientDriver 
      </property> 
		
      <property name = "dialect">
         NHibernate.Dialect.MsSql2008Dialect
      </property> 
		
      <property name = "show_sql">true</property> 
   </session-factory> 

</hibernate-configuration>

Dalam contoh ini, kami akan mengerjakan dua kelas domain, Pelanggan dan Pesanan.

Berikut adalah implementasi file Customer.cs di mana kita memiliki dua kelas, satu adalah kelas Pelanggan dan yang lainnya adalah kelas Lokasi di mana objek digunakan sebagai alamat di kelas Pelanggan.

using System; 
using System.Text; 
using Iesi.Collections.Generic;

namespace NHibernateDemo { 

   public class Customer { 
      
      public Customer() { 
         MemberSince = DateTime.UtcNow; 
         Orders = new HashedSet<Order>(); 
      } 
      
      public virtual Guid Id { get; set; } 
      public virtual string FirstName { get; set; } 
      public virtual string LastName { get; set; } 
      public virtual double AverageRating { get; set; } 
      public virtual int Points { get; set; } 
		
      public virtual bool HasGoldStatus { get; set; }
      public virtual DateTime MemberSince { get; set; } 
      public virtual CustomerCreditRating CreditRating { get; set; } 
      public virtual Location Address { get; set; }
		
      public virtual ISet<Order> Orders { get; set; }
      public virtual void AddOrder(Order order) { Orders.Add(order); order.Customer = this; }
      
      public override string ToString() { 
         var result = new StringBuilder();
			
         result.AppendFormat("{1} {2} ({0})\r\n\tPoints: {3}\r\n\tHasGoldStatus:
            {4}\r\n\tMemberSince: {5} ({7})\r\n\tCreditRating: {6}\r\n\tAverageRating:
            {8}\r\n", Id, FirstName, LastName, Points, HasGoldStatus, MemberSince,
            CreditRating, MemberSince.Kind, AverageRating);
            result.AppendLine("\tOrders:"); 
         
         foreach(var order in Orders) { 
            result.AppendLine("\t\t" + order); 
         } 
			
         return result.ToString(); 
      } 
   }
   
   public class Location { 
      public virtual string Street { get; set; } 
      public virtual string City { get; set; } 
      public virtual string Province { get; set; } 
      public virtual string Country { get; set; } 
   }
   
   public enum CustomerCreditRating { 
      Excellent,
      VeryVeryGood, 
      VeryGood, 
      Good, 
      Neutral, 
      Poor, 
      Terrible 
   } 
}

Ini file pemetaannya Customer.hbm.xml di mana kelas Pelanggan dipetakan ke tabel Pelanggan.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo" 
   namespace = "NHibernateDemo"> 
	
   <class name = "Customer"> 
   
      <id name = "Id"> 
         <generator class = "guid.comb"/> 
      </id> 

      <property name = "FirstName"/> 
      <property name = "LastName"/> 
      <property name = "AverageRating"/> 
      <property name = "Points"/> 
      <property name = "HasGoldStatus"/> 
      <property name = "MemberSince" type = "UtcDateTime"/> 
      <property name = "CreditRating" type = "CustomerCreditRatingType"/>
      
      <component name = "Address"> 
         <property name = "Street"/> 
         <property name = "City"/> 
         <property name = "Province"/> 
         <property name = "Country"/> 
      </component> 

   </class> 
</hibernate-mapping>

Kami juga memiliki Order Class dan inilah implementasinya Order.cs mengajukan.

using System; using Iesi.Collections.Generic;

namespace NHibernateDemo { 

   public class Order { 
      
      public virtual Guid Id { get; set; } 
      public virtual DateTime Ordered { get; set; } 
      public virtual DateTime? Shipped { get; set; }
      public virtual Location ShipTo { get; set; } 
      public virtual Customer Customer { get; set; }
      
      public override string ToString() { 
         return string.Format("Order Id: {0}", Id); 
      } 
   } 
}

Hubungan Banyak-ke-Satu

Kita juga perlu memetakan kelas Order ke tabel Order di database, jadi inilah implementasi dari Order.hbm.xml mengajukan.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo" 
   namespace = "NHibernateDemo"> 

   <class name = "Order" table = "`Order`"> 
   
      <id name = "Id"> 
         <generator class = "guid.comb"/> 
      </id> 
		
      <property name = "Ordered"/> 
      <property name = "Shipped"/> 
   
      <component name = "ShipTo"> 
         <property name = "Street"/> 
         <property name = "City"/> 
         <property name = "Province"/> 
         <property name = "Country"/> 
      </component> 

      <!--<many-to-one name = "Customer" column = "CustomerId" cascade =
         "save-update"/>--> 
			
   </class> 
</hibernate-mapping>

Hubungan Satu-ke-Banyak

Di sini, kita akan melihat hubungan satu ke banyak, dalam hal ini, antara pelanggan dan pesanan. Kami memiliki pelanggan di sini, kami sedang membuat yang baru, dan Anda dapat melihat bahwa koleksi tersebut diinisialisasi dengan sepasang pesanan berikut.

private static Customer CreateCustomer() { 
   
   var customer = new Customer { 
      FirstName = "John", 
      LastName = "Doe", 
      Points = 100, 
      HasGoldStatus = true, 
      MemberSince = new DateTime(2012, 1, 1), 
      CreditRating = CustomerCreditRating.Good, 
      AverageRating = 42.42424242, 
      Address = CreateLocation() 
   }; 
   
   var order1 = new Order { 
      Ordered = DateTime.Now 
   }; 
   
   customer.AddOrder(order1); 
   var order2 = new Order { 
      Ordered = DateTime.Now.AddDays(-1), 
      Shipped = DateTime.Now, 
      ShipTo = CreateLocation() 
   }; 
   
   customer.AddOrder(order2); 
   return customer; 
}

Jadi kita akan membuat pelanggan baru dan kemudian menyimpannya, setelah menyimpannya, kita akan menemukan ID dan kemudian memuatnya kembali di sesi lain dalam metode Utama seperti yang ditunjukkan pada program berikut.

private static void Main() { 

   var cfg = ConfigureNHibernate(); 
   var sessionFactory = cfg.BuildSessionFactory();
   
   Guid id; 
   using(var session = sessionFactory.OpenSession()) 
	
   using(var tx = session.BeginTransaction()) { 
      var newCustomer = CreateCustomer(); 
      Console.WriteLine("New Customer:"); 
      Console.WriteLine(newCustomer);
      session.Save(newCustomer); 
      id = newCustomer.Id; 
      tx.Commit(); 
   }
   
   using(var session = sessionFactory.OpenSession()) 
	
   using(var tx = session.BeginTransaction()) { 
      var reloaded = session.Load<Customer>(id); 
      Console.WriteLine("Reloaded:"); 
      Console.WriteLine(reloaded); 
      tx.Commit(); 
   }
   
   Console.WriteLine("Press <ENTER> to exit..."); 
   Console.ReadLine(); 
}

Ini lengkapnya Program.cs implementasi file.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Driver; 
using NHibernate.Linq;

namespace NHibernateDemo {
 
   internal class Program { 
	
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         
         Guid id; 
         using(var session = sessionFactory.OpenSession())
			
         using(var tx = session.BeginTransaction()) { 
            var newCustomer = CreateCustomer(); 
            Console.WriteLine("New Customer:"); 
            Console.WriteLine(newCustomer); 
            session.Save(newCustomer); 
            id = newCustomer.Id; 
            tx.Commit(); 
         } 
         
         using(var session = sessionFactory.OpenSession()) 
			
         using(var tx = session.BeginTransaction()) { 
            var reloaded = session.Load<Customer>(id); 
            Console.WriteLine("Reloaded:"); 
            Console.WriteLine(reloaded); 
            tx.Commit();
         }
         
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine();
      }
      
      private static Customer CreateCustomer() { 
		
         var customer = new Customer { 
            FirstName = "John", 
            LastName = "Doe", 
            Points = 100, 
            HasGoldStatus = true, 
            MemberSince = new DateTime(2012, 1, 1), 
            CreditRating = CustomerCreditRating.Good, 
            AverageRating = 42.42424242, 
            Address = CreateLocation() 
         }; 
         
         var order1 = new Order { 
            Ordered = DateTime.Now
         }; 
         
         customer.AddOrder(order1); 
			
         var order2 = new Order { 
            Ordered = DateTime.Now.AddDays(-1), 
            Shipped = DateTime.Now, 
            ShipTo = CreateLocation() 
         }; 
         
         customer.AddOrder(order2); 
         return customer; 
      } 
      
      private static Location CreateLocation() { 
		
         return new Location { 
            Street = "123 Somewhere Avenue", 
            City = "Nowhere", 
            Province = "Alberta", 
            Country = "Canada" 
         }; 
      } 
      
      private static Configuration ConfigureNHibernate() { 
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x =&ht; { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10; x.BatchSize = 10; 
         }); 
         
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Saat Anda menjalankan aplikasi ini, Anda akan melihat output berikut.

New Customer:

John Doe (00000000-0000-0000-0000-000000000000)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Unspecified)
   CreditRating: Good
   AverageRating: 42.42424242

   Orders:
      Order Id: 00000000-0000-0000-0000-000000000000
      Order Id: 00000000-0000-0000-0000-000000000000

Reloaded:
John Doe (9b0fcf10-83f6-4f39-bda5-a5b800ede2ba)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
Press <ENTER> to exit...

Seperti yang Anda lihat bahwa awalnya pelanggan memiliki 2 pesanan, tetapi ketika kami memuatnya kembali, tidak ada pesanan yang terlihat. Jika Anda melihatcustomer.hbm.xmlfile, Anda dapat melihat di sini bahwa kami tidak memetakan koleksi pesanan yang sebenarnya. Jadi NHibernate tidak tahu apa-apa tentang itu. Mari lanjutkan dan tambahkan.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" 
   assembly = "NHibernateDemo" namespace = "NHibernateDemo">
	
   <class name = "Customer"> 
      
      <id name = "Id">
         <generator class = "guid.comb"/> 
      </id> 
      
      <property name = "FirstName"/>
      <property name = "LastName"/> 
      <property name = "AverageRating"/> 
      <property name = "Points"/> 
      <property name = "HasGoldStatus"/> 
      <property name = "MemberSince" type = "UtcDateTime"/> 
      <property name = "CreditRating" type = "CustomerCreditRatingType"/>
      
      <component name = "Address"> 
         <property name = "Street"/> 
         <property name = "City"/> 
         <property name = "Province"/> 
         <property name = "Country"/> 
      </component>
      
      <set name = "Orders" table = "`Order`"> 
         <key column = "CustomerId"/> 
         <one-to-many class = "Order"/> 
      </set> 
   
   </class> 
</hibernate-mapping>

Ini adalah satu set dan nama koleksi ini adalah 'Pesanan', yang disimpan dalam tabel yang disebut pesanan. Kita perlu menentukan kunci yang merupakan nama kunci asing atau untuk menemukan pesanan. Pesanan ini diidentifikasi atau menjadi milik pelanggan melalui ID pelanggan. Dan kemudian saya harus mencatat bahwa ini adalah hubungan satu-ke-banyak dan dengan kelas pesanan.

Kami juga perlu sedikit mengubah metode Utama dengan menyimpan pesanan pelanggan baru ke database seperti yang ditunjukkan pada program berikut.

private static void Main() { 

   var cfg = ConfigureNHibernate(); 
   var sessionFactory = cfg.BuildSessionFactory();
   
   Guid id; 
   using(var session = sessionFactory.OpenSession()) 
	
   using(var tx = session.BeginTransaction()) {
      var newCustomer = CreateCustomer(); 
      Console.WriteLine("New Customer:"); 
      Console.WriteLine(newCustomer);
      session.Save(newCustomer); 
      
      foreach (var order in newCustomer.Orders) { 
         session.Save(order); 
      } 
		
      id = newCustomer.Id; 
      tx.Commit(); 
   }
   
   using(var session = sessionFactory.OpenSession()) 
	
   using(var tx = session.BeginTransaction()) { 
      var reloaded = session.Load<Customer>(id); 
      Console.WriteLine("The orders were ordered by: "); 
      
      foreach (var order in reloaded.Orders) { 
         Console.WriteLine(order.Customer); 
      } 
		
      tx.Commit(); 
   }
   Console.WriteLine("Press <ENTER> to exit..."); Console.ReadLine();
}

Kami juga telah menentukan pelanggan mana yang memesan produk tertentu itu. Jadi kita perlu membuat hubungan banyak-ke-satu untuk menghubungkan kembali pesanan itu dengan pelanggan itu.

Jadi, mari kita masuk ke Order.hbm.xml file dan tambahkan banyak ke satu, lalu beri nama bidang pelanggan dan kolom dengan ID pelanggan.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo"
   namespace = "NHibernateDemo"> 
	
   <class name = "Order" table = "`Order`">
      
      <id name = "Id"> 
         <generator class = "guid.comb"/> 
      </id>
      
      <property name = "Ordered"/> 
      <property name = "Shipped"/> 
      
      <component name = "ShipTo"> 
         <property name = "Street"/> 
         <property name = "City"/> 
         <property name = "Province"/> 
         <property name = "Country"/> 
      </component> 

      <many-to-one name = "Customer" column = "CustomerId"/> 
		
   </class> 
</hibernate-mapping>

Ayo jalankan aplikasi ini lagi dan sekarang Anda akan melihat output berikut.

New Customer:
John Doe (00000000-0000-0000-0000-000000000000)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Unspecified)
   CreditRating: Good
   AverageRating: 42.42424242

   Orders:
      Order Id: 00000000-0000-0000-0000-000000000000
      Order Id: 00000000-0000-0000-0000-000000000000

Reloaded:
John Doe (660a6f29-650e-4380-99e0-a5b800febbde)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: 57314deb-e023-4e55-ac1e-a5b800febbe3
      Order Id: fc065683-d5f5-484b-ae42-a5b800febbe3

The orders were ordered by:
John Doe (660a6f29-650e-4380-99e0-a5b800febbde)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: 57314deb-e023-4e55-ac1e-a5b800febbe3
      Order Id: fc065683-d5f5-484b-ae42-a5b800febbe3

John Doe (660a6f29-650e-4380-99e0-a5b800febbde)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: 57314deb-e023-4e55-ac1e-a5b800febbe3
      Order Id: fc065683-d5f5-484b-ae42-a5b800febbe3
		
Press <ENTER> to exit...

Dalam bab ini, kami akan membahas bagaimana merepresentasikan koleksi. Ada berbagai jenis koleksi yang dapat kami gunakan di dalam NHibernate seperti -

  • Lists
  • Sets
  • Bags

Sekarang, dari perspektif .NET, kita biasanya berurusan dengan daftar atau menyukai struktur data, daftar, kamus yang sangat sederhana. .NET tidak memiliki beragam jenis koleksi yang berbeda. Jadi mengapa NHibernate membutuhkan semua jenis yang berbeda ini? Ini benar-benar kembali ke database.

Daftar

  • Daftar adalah kumpulan elemen yang tidak selalu unik.

  • Kita bisa memetakannya menggunakan IList <T>.

  • Jadi meskipun kita mungkin secara konvensional memiliki daftar alamat, dan dari sudut pandang aplikasi kita tahu bahwa elemennya unik, tidak ada dalam daftar yang mencegah kita memasukkan elemen duplikat dalam daftar itu.

Set

  • Satu set adalah kumpulan elemen unik yang tidak berurutan. Jika Anda mencoba memasukkan 2 elemen duplikat ke dalam satu set, itu akan memunculkan pengecualian.

  • Tidak ada yang spesifik di NHibernate tentang itu.

  • Ini hanya cara yang nyaman untuk memiliki implementasi set generik. Jika Anda menggunakan .NET 4, Anda dapat menggunakan yang baruHashSet <T> untuk mewakili ini, tetapi di sebagian besar aplikasi NHibernate, kami menyatakan ini adalah ISet.

  • Ini adalah unordered, jika Anda menarik kembali daftar alamat dari database atau daftar pesanan, Anda tidak tahu apa pesanan mereka datang kecuali Anda memasukkan Urutan berdasarkan klausa tertentu.

  • Jadi secara umum, data yang Anda tarik kembali dari database adalah kumpulan.

  • Mereka adalah koleksi elemen unik yang tidak berurutan.

Tas

  • Koleksi umum lainnya yang akan kita lihat di dunia database adalah tas, yang hanya seperti satu set kecuali dapat memiliki elemen duplikat.

  • Di dunia .NET, kami mewakili ini dengan IList.

Set mungkin yang paling umum, tetapi Anda juga akan melihat daftar dan tas tergantung pada aplikasi Anda. Mari kita lihat di bawah inicustomer.hbm.xml file dari bab terakhir di mana pesanan Set didefinisikan.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo" 
   namespace = "NHibernateDemo"> 
	
   <class name = "Customer"> 
      
      <id name = "Id"> 
         <generator class = "guid.comb"/> 
      </id> 
   
      <property name = "FirstName"/> 
      <property name = "LastName"/> 
      <property name = "AverageRating"/> 
      <property name = "Points"/> 
      <property name = "HasGoldStatus"/> 
      <property name = "MemberSince" type = "UtcDateTime"/> 
      <property name = "CreditRating" type = "CustomerCreditRatingType"/>
      
      <component name = "Address"> 
         <property name = "Street"/> 
         <property name = "City"/> 
         <property name = "Province"/> 
         <property name = "Country"/> 
      </component>
      
      <set name = "Orders" table = "`Order`"> 
         <key column = "CustomerId"/> 
         <one-to-many class = "Order"/> 
      </set> 
   
   </class> 
</hibernate-mapping>

Seperti yang Anda lihat, kami telah memetakan koleksi pesanan sebagai satu set. Ingatlah bahwa satu set adalah kumpulan elemen unik yang tidak berurutan.

Sekarang, jika Anda melihat kelas Pelanggan, Anda akan melihat bahwa properti Pesanan ditentukan dengan ISet seperti yang ditunjukkan dalam program berikut.

public virtual ISet<Order> Orders { get; set; }

Sekarang ketika aplikasi ini dijalankan, Anda akan melihat output berikut.

New Customer:
John Doe (00000000-0000-0000-0000-000000000000)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Unspecified)
   CreditRating: Good
   AverageRating: 42.42424242

   Orders:
      Order Id: 00000000-0000-0000-0000-000000000000
      Order Id: 00000000-0000-0000-0000-000000000000

Reloaded:
John Doe (1f248133-b50a-4ad7-9915-a5b8017d0ff1)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: c41af8f2-7124-42a7-91c5-a5b8017d0ff6
      Order Id: 657f6bb0-1f42-45fc-8fc7-a5b8017d0ff7

The orders were ordered by:
John Doe (1f248133-b50a-4ad7-9915-a5b8017d0ff1)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: c41af8f2-7124-42a7-91c5-a5b8017d0ff6
      Order Id: 657f6bb0-1f42-45fc-8fc7-a5b8017d0ff7

John Doe (1f248133-b50a-4ad7-9915-a5b8017d0ff1)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: c41af8f2-7124-42a7-91c5-a5b8017d0ff6
      Order Id: 657f6bb0-1f42-45fc-8fc7-a5b8017d0ff7
		
Press <ENTER> to exit...

Jika item dalam koleksi tidak harus unik, jika Anda dapat memiliki beberapa pesanan dengan kunci utama yang sama yang terjadi beberapa kali dalam koleksi ini, maka ini akan lebih baik dipetakan sebagai tas seperti yang ditunjukkan dalam program berikut.

<bag name = "Orders" table = "`Order`"> 
   <key column = "CustomerId"/> 
   <one-to-many class = "Order"/> 
</bag>

Sekarang, jika Anda menjalankan aplikasi ini, Anda akan mendapatkan pengecualian karena jika kita melihat kelas pelanggan, Anda akan melihat bahwa pesanan ditandai sebagai ISet dalam kode C #.

Jadi kita juga perlu mengubahnya menjadi IList dan kemudian di sini, kita perlu mengubah dari HashSet ke Daftar di konstruktor.

public class Customer { 
   public Customer() { 
      MemberSince = DateTime.UtcNow; 
      Orders = new List<Order>(); 
   } 
	
   public virtual Guid Id { get; set; } 
   public virtual string FirstName { get; set; } 
   public virtual string LastName { get; set; } 
   public virtual double AverageRating { get; set; } 
   public virtual int Points { get; set; } 
	
   public virtual bool HasGoldStatus { get; set; } 
   public virtual DateTime MemberSince { get; set; } 
   public virtual CustomerCreditRating CreditRating { get; set; } 
   public virtual Location Address { get; set; }
   public virtual IList<Order> Orders { get; set; }
   public virtual void AddOrder(Order order) { Orders.Add(order); order.Customer = this; }
   
   public override string ToString() { 
      var result = new StringBuilder(); 
		
      result.AppendFormat("{1} {2} ({0})\r\n\tPoints: {3}\r\n\tHasGoldStatus:
         {4}\r\n\tMemberSince: {5} ({7})\r\n\tCreditRating: {6}\r\n\tAverageRating:
         {8}\r\n", Id, FirstName, LastName, Points, HasGoldStatus, MemberSince,
         CreditRating, MemberSince.Kind, AverageRating); result.AppendLine("\tOrders:"); 
      
      foreach(var order in Orders) { 
         result.AppendLine("\t\t" + order); 
      } 
		
      return result.ToString(); 
   } 
}

Saat Anda menjalankan aplikasi, Anda akan melihat perilaku yang sama. Namun, sekarang kita dapat memiliki pesanan yang terjadi beberapa kali dalam koleksi yang sama.

John Doe (00000000-0000-0000-0000-000000000000)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Unspecified)
   CreditRating: Good
   AverageRating: 42.42424242

   Orders:
      Order Id: 00000000-0000-0000-0000-000000000000
      Order Id: 00000000-0000-0000-0000-000000000000

Reloaded:
John Doe (fbde48f5-d620-4d1c-9a7f-a5b8017c3280)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: 6dd7dbdb-354f-4c82-9c39-a5b8017c3286
      Order Id: 9b3e2441-a81b-404d-9aed-a5b8017c3287

The orders were ordered by:
John Doe (fbde48f5-d620-4d1c-9a7f-a5b8017c3280)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: 6dd7dbdb-354f-4c82-9c39-a5b8017c3286
      Order Id: 9b3e2441-a81b-404d-9aed-a5b8017c3287

John Doe (fbde48f5-d620-4d1c-9a7f-a5b8017c3280)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: 6dd7dbdb-354f-4c82-9c39-a5b8017c3286
      Order Id: 9b3e2441-a81b-404d-9aed-a5b8017c3287
		
Press <ENTER> to exit...

Di bab ini, kami akan membahas cara menggunakan fitur Kaskade. Jika Anda memiliki satu set atau kumpulan item atau hubungan antara dua kelas seperti pelanggan dan pesanan kami dan memiliki hubungan kunci asing. Jika kami menghapus pelanggan secara default, NHibernate tidak melakukan apa pun pada objek turunan, jadi objek yang dimiliki pelanggan tersebut dan kami dapat menjadi pesanan yatim piatu.

  • Kami juga dapat melanggar batasan kunci asing, sehingga kami dapat menggunakan gagasan kaskade.

  • Secara default, NHibernate tidak menurunkan operasi ke objek anak.

  • Alasannya adalah Anda dapat memiliki hubungan seperti pelanggan yang memiliki alamat pengiriman default dan alamat pengiriman tersebut dibagikan dengan banyak pelanggan yang berbeda.

  • Jadi, Anda tidak ingin menurunkan hubungan itu karena pelanggan lain masih merujuknya.

  • Jadi seluruh gagasan tentang kaskade adalah untuk memberi tahu NHibernate bagaimana menangani entitas anaknya.

Ada beberapa opsi berbeda untuk cascading, yaitu sebagai berikut -

  • none - yang merupakan default dan artinya tidak ada cascading.

  • all - yang akan disimpan, diperbarui, dan dihapus secara kaskade.

  • save-update - itu akan menurun, menyimpan dan memperbarui.

  • delete - itu akan menghapus kaskade.

  • all-delete-orphan - itu khusus yang cukup sering digunakan dan sama dengan Semua Kecuali, jika menemukan baris Hapus-yatim piatu, itu akan menghapusnya juga.

Anda dapat menentukan default di file hbm.xml file, sehingga Anda dapat menyediakan kaskade default pada elemen pemetaan Hibernate atau Anda juga dapat menentukannya untuk koleksi dan hubungan tertentu seperti many-to-one.

Mari kita lihat contoh kaskade sederhana, mari kita perbaiki masalah dalam program, di mana kita harus secara manual men-cascade penyimpanan ke pesanan seperti yang ditunjukkan pada kode berikut.

using(var session = sessionFactory.OpenSession()) 

using(var tx = session.BeginTransaction()) { 
   var newCustomer = CreateCustomer(); 
   Console.WriteLine("New Customer:"); 
   Console.WriteLine(newCustomer); 
   session.Save(newCustomer); 
	
   foreach (var order in newCustomer.Orders) { 
      session.Save(order); 
   } 
	
   id = newCustomer.Id; 
   tx.Commit(); 
}

Pada potongan kode di atas, Anda dapat melihat bahwa kami menyimpan semua pesanan secara manual untuk pelanggan. Sekarang mari kita hapus kode kaskade manual di mana semua pesanan disimpan.

using(var session = sessionFactory.OpenSession())
 
using(var tx = session.BeginTransaction()) { 
   var newCustomer = CreateCustomer(); 
   Console.WriteLine("New Customer:"); 
   Console.WriteLine(newCustomer);
	
   session.Save(newCustomer); 
   id = newCustomer.Id; 
   tx.Commit(); 
}

Kita perlu menentukan opsi cascade di customer.hbm.xml.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo"
   namespace = "NHibernateDemo"> 
	
   <class name = "Customer"> 
   
      <id name = "Id"> 
         <generator class = "guid.comb"/> 
      </id> 
      
      <property name = "FirstName"/> 
      <property name = "LastName"/> 
      <property name = "AverageRating"/> 
      <property name = "Points"/> 
      <property name = "HasGoldStatus"/> 
      <property name = "MemberSince" type = "UtcDateTime"/> 
      <property name = "CreditRating" type = "CustomerCreditRatingType"/>
      
      <component name = "Address"> 
         <property name = "Street"/> 
         <property name = "City"/> 
         <property name = "Province"/> 
         <property name = "Country"/> 
      </component>
      
      <set name = "Orders" table = "`Order`" cascade = "all-delete-orphan"> 
         <key column = "CustomerId"/> 
         <one-to-many class = "Order"/> 
      </set> 
   
   </class> 
</hibernate-mapping>
  • Sekarang, pesanan sepenuhnya menjadi milik pelanggan. Jadi jika pelanggan dihapus dari database, aplikasi kita di sini ingin menghapus semua pesanan tersebut, termasuk yang mungkin telah menjadi yatim piatu.

  • Ini akan berakhir dengan melakukan penghapusan. Dengan itu, akan tertulis hapus dari tabel pesanan, di mana ID pelanggan sama dengan pelanggan yang Anda hapus.

  • Jadi Anda benar-benar dapat meningkatkan penghapusan ini. Begitu pula denganAll, itu akan menyimpan, memperbarui, dan menghapus.

Sekarang ketika Anda menjalankan aplikasi ini, Anda akan melihat output berikut.

New Customer:
John Doe (00000000-0000-0000-0000-000000000000)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Unspecified)
   CreditRating: Good
   AverageRating: 42.42424242

   Orders:
      Order Id: 00000000-0000-0000-0000-000000000000
      Order Id: 00000000-0000-0000-0000-000000000000

Reloaded:
John Doe (10b2a3d7-7fcf-483c-b1da-a5bb00b8512e)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: e6680e30-5b3b-4efa-b017-a5bb00b85133
      Order Id: b03858e7-8c36-4555-8878-a5bb00b85134

The orders were ordered by:
John Doe (10b2a3d7-7fcf-483c-b1da-a5bb00b8512e)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: e6680e30-5b3b-4efa-b017-a5bb00b85133
      Order Id: b03858e7-8c36-4555-8878-a5bb00b85134

John Doe (10b2a3d7-7fcf-483c-b1da-a5bb00b8512e)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: e6680e30-5b3b-4efa-b017-a5bb00b85133
      Order Id: b03858e7-8c36-4555-8878-a5bb00b85134
		
Press <ENTER> to exit...

Seperti yang Anda lihat bahwa kami telah menghapus kode dari program yang mengalir secara manual dan aplikasi kami masih berfungsi.

Jadi tergantung pada hubungan Anda, Anda mungkin ingin menurunkannya. Sekarang, mari kita lihat hubungan kaskade yang berbeda. Ayo pergi keOrder.hbm.xml file dan kita dapat mengalirkan hubungan banyak-ke-satu itu.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo"
   namespace = "NHibernateDemo"> 
   
   <class name = "Order" table = "`Order`"> 
	
      <id name = "Id"> 
         <generator class = "guid.comb"/> 
      </id> 

      <property name = "Ordered"/> 
      <property name = "Shipped"/> 
      
      <component name = "ShipTo"> 
         <property name = "Street"/> 
         <property name = "City"/> 
         <property name = "Province"/> 
         <property name = "Country"/> 
      </component> 
      
      <many-to-one name = "Customer" column = "CustomerId" cascade = "save-update"/>
		
   </class> 
</hibernate-mapping>

Jadi jika kita membuat pesanan baru dan ada pelanggan baru yang melekat padanya dan kita berkata, simpan pesanan itu, kita mungkin ingin menurunkannya. Tetapi satu hal yang mungkin tidak ingin kami lakukan adalah jika pesanan dihapus untuk menghapus pelanggan terkait.

Jadi di sini, kami ingin melakukan pembaruan penyimpanan, jadi dengan menggunakan simpan-pembaruan, ini akan menurunkan penyimpanan atau pembaruan apa pun ke pelanggan itu. Jadi, jika kita mendapatkan pelanggan baru atau jika kita berganti pelanggan, itu akan menurunkannya. Jika itu adalah hapus, itu tidak akan menghapusnya dari database.

Jadi menjalankan aplikasi kita lagi, semuanya masih berfungsi seperti yang diharapkan.

New Customer:
John Doe (00000000-0000-0000-0000-000000000000)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Unspecified)
   CreditRating: Good
   AverageRating: 42.42424242

   Orders:
      Id: 00000000-0000-0000-0000-000000000000
      Order Id: 00000000-0000-0000-0000-000000000000

Reloaded:
John Doe (10b2a3d7-7fcf-483c-b1da-a5bb00b8512e)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: e6680e30-5b3b-4efa-b017-a5bb00b85133
      Order Id: b03858e7-8c36-4555-8878-a5bb00b85134

The orders were ordered by:
John Doe (10b2a3d7-7fcf-483c-b1da-a5bb00b8512e)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: e6680e30-5b3b-4efa-b017-a5bb00b85133
      Order Id: b03858e7-8c36-4555-8878-a5bb00b85134
      John Doe (10b2a3d7-7fcf-483c-b1da-a5bb00b8512e)
		
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: e6680e30-5b3b-4efa-b017-a5bb00b85133
      Order Id: b03858e7-8c36-4555-8878-a5bb00b85134
		
Press <ENTER> to exit...

Sekarang Anda harus melihat aplikasi Anda, ingat bahwa defaultnya adalah Tidak Ada dan Anda harus memikirkan entitas Anda dan hubungan Anda di antara mereka untuk menentukan kaskade yang sesuai untuk setiap entitas Anda serta setiap hubungan Anda dalam database itu.

Dalam bab ini, kita akan membahas fitur pemuatan lambat. Ini adalah konsep yang sepenuhnya berbeda secara default dan NHibernate tidak memiliki pemuatan lambat, misalnya jika Anda memuat pelanggan, itu tidak akan memuat semua pesanan.

  • Koleksi pesanan akan dimuat sesuai permintaan.

  • Pengaitan apa pun, apakah itu many-to-one atau collection secara default dimuat lambat, ini memerlukan Open ISession.

  • Jika Anda telah menutup sesi Anda, atau jika Anda telah melakukan transaksi, Anda bisa mendapatkan pengecualian pemuatan lambat yang tidak dapat menarik objek tambahan tersebut.

  • Anda harus berhati-hati tentang pemuatan lambat dan berapa banyak data yang sebenarnya Anda butuhkan.

  • Anda dapat menonaktifkan pemuatan lambat untuk seluruh pengaitan atau Anda dapat menempatkan pemuatan lambat sama dengan salah atau Anda juga dapat menentukan strategi pengambilan.

Ini dia Program.cs implementasi file.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Driver; 
using NHibernate.Linq;

namespace NHibernateDemo { 

   internal class Program { 
	
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         
         Guid id; 
         using(var session = sessionFactory.OpenSession()) 
			
         using(var tx = session.BeginTransaction()) {
            var newCustomer = CreateCustomer(); 
            Console.WriteLine("New Customer:"); 
            Console.WriteLine(newCustomer); 
            session.Save(newCustomer); 
            id = newCustomer.Id; 
            tx.Commit(); 
         }
         
         using(var session = sessionFactory.OpenSession()) 
			
         using(var tx = session.BeginTransaction()) { 
            var reloaded = session.Load<Customer>(id); 
            Console.WriteLine("Reloaded:"); 
            Console.WriteLine(reloaded); 
            Console.WriteLine("The orders were ordered by: "); 
            
            foreach (var order in reloaded.Orders) { 
               Console.WriteLine(order.Customer); 
            } 
				
            tx.Commit(); 
         }
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
		
      private static Customer CreateCustomer() { 
         
         var customer = new Customer { 
            FirstName = "John", 
            LastName = "Doe", 
            Points =100, 
            HasGoldStatus = true, 
            MemberSince = new DateTime(2012, 1, 1),
            CreditRating = CustomerCreditRating.Good,
            AverageRating = 42.42424242, 
            Address = CreateLocation() 
         }; 
			
         var order1 = new Order { Ordered = DateTime.Now }; 
         customer.AddOrder(order1); 
         
         var order2 = new Order { 
            Ordered = DateTime.Now.AddDays(-1), 
            Shipped = DateTime.Now, 
            ShipTo = CreateLocation() 
         }; 
			
         customer.AddOrder(order2); return customer; 
      }
		
      private static Location CreateLocation() { 
         return new Location { 
            Street = "123 Somewhere Avenue", 
            City = "Nowhere", 
            Province = "Alberta", 
            Country = "Canada" 
         }; 
      }
		
      private static Configuration ConfigureNHibernate() { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect<(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10;
            x.BatchSize = 10;
         }); 
         
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Untuk memahami hal ini, mari kita jalankan aplikasi dan lihat di NHibernate Profiler.

Seperti yang Anda lihat bahwa kami memiliki Pilih Dari Pelanggan, diberi ID pelanggan tertentu dan kemudian kami juga memiliki tabel Pilih Dari Pesanan, ketika itu benar-benar mengakses koleksi pelanggan itu.

Jadi kami memiliki 2 perjalanan pulang pergi ke database. Sekarang, terkadang, kami ingin mengoptimalkan ini. Untuk melakukan ini, ayo pergi kecustomer.hbm.xml mengajukan dan menambahkan strategi pengambilan dan memintanya untuk melakukan pengambilan gabungan.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo"
   namespace = "NHibernateDemo"> 
   
   <class name = "Customer"> 
	
      <id name = "Id"> 
         <generator class = "guid.comb"/> 
      </id> 
   
      <property name = "FirstName"/> 
      <property name = "LastName"/> 
      <property name = "AverageRating"/> 
      <property name = "Points"/> 
      <property name = "HasGoldStatus"/> 
      <property name = "MemberSince" type = "UtcDateTime"/> 
      <property name = "CreditRating" type = "CustomerCreditRatingType"/>
      
      <component name = "Address"> 
         <property name = "Street"/> 
         <property name = "City"/> 
         <property name = "Province"/> 
         <property name = "Country"/> 
      </component>
      
      <set name = "Orders" table = "`Order`" cascade = "all-delete-orphan" 
         fetch = "join"> 
         <key column = "CustomerId"/> 
         <one-to-many class = "Order"/> 
      </set> 
   
   </class> 
</hibernate-mapping>

Seperti yang Anda lihat bahwa kami belum mengubah kode apa pun dalam aplikasi kami, kami baru saja menambahkan strategi pengambilan di customer.hbm.xml. Mari kita jalankan aplikasi ini lagi, itu masih berperilaku persis sama. Mari kita lihat Profiler NHibernate.

  • Sebelumnya, program memiliki dua perjalanan bolak-balik ke database, sekarang hanya memiliki satu dan itu karena melakukan penggabungan luar kiri di sini.

  • Kita dapat melihat bahwa ia melakukan penggabungan luar kiri antara tabel pelanggan dan tabel pesanan berdasarkan ID pelanggan, dan oleh karena itu, ia dapat memuat semua informasi itu sekaligus.

  • Kami telah menyimpan 1 perjalanan pulang pergi ke database.

  • Sisi bawahnya adalah bahwa informasi pelanggan akan diduplikasi pada kedua baris dan itulah cara kerja gabungan luar kiri SQL.

  • Jadi dengan strategi pengambilan, kami menarik kembali sedikit lebih banyak data dan kami menyimpan perjalanan bolak-balik.

Anda juga dapat melakukan ini di tingkat kueri, jadi mari kita pergi ke Program.cs file dan lihat contoh dimuat ulang yang lebih sederhana.

using(var session = sessionFactory.OpenSession()) 

using(var tx = session.BeginTransaction()) { 
   //var query = from customer in session.Query<Customer>() 
   // select customer; 
   //var reloaded = query.Fetch(x => x.Orders).ToList();
	
   var reloaded = session.Load<Customer>(id); 
   Console.WriteLine("Reloaded:"); 
   Console.WriteLine(reloaded); 
   Console.WriteLine("The orders were ordered by: "); 
   
   foreach (var order in reloaded.Orders) { 
      Console.WriteLine(order.Customer); 
   } 
	
   tx.Commit(); 
}

Di sini, kami melakukan pemuatan oleh pelanggan. Sekarang mari kita ubah menjadi kueri dan kami akan menggunakan kueri tautan seperti yang ditunjukkan pada kode berikut.

using(var session = sessionFactory.OpenSession()) 

using(var tx = session.BeginTransaction()) {
   var query = from customer in session.Query<Customer>() 
   where customer.Id == id select customer; 
   var reloaded = query.Fetch(x => x.Orders).ToList().First();
	
   Console.WriteLine("Reloaded:"); 
   Console.WriteLine(reloaded); 
	
   tx.Commit();
}

Mari kita juga menghapus strategi pengambilan dari customer.hbm.xml mengajukan.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo"
   namespace = "NHibernateDemo"> 

   <class name = "Customer"> 
	
      <id name = "Id"> 
         <generator class = "guid.comb"/> 
      </id> 
   
      <property name = "FirstName"/> 
      <property name = "LastName"/>
      <property name = "AverageRating"/> 
      <property name = "Points"/> 
      <property name = "HasGoldStatus"/> 
      <property name = "MemberSince" type = "UtcDateTime"/> 
      <property name = "CreditRating" type = "CustomerCreditRatingType"/>
   
      <component name = "Address"> 
         <property name = "Street"/> 
         <property name = "City"/> 
         <property name = "Province"/> 
         <property name = "Country"/> 
      </component>
   
      <set name = "Orders" table = "`Order`" cascade = "all-delete-orphan"> 
         <key column = "CustomerId"/> 
         <one-to-many class = "Order"/> 
      </set> 
   
   </class> 
</hibernate-mapping>

Jalankan aplikasi ini lagi dan Anda akan melihat output berikut.

New Customer:
John Doe (00000000-0000-0000-0000-000000000000)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Unspecified)
   CreditRating: Good
   AverageRating: 42.42424242

   Orders:
      Order Id: 00000000-0000-0000-0000-000000000000
      Order Id: 00000000-0000-0000-0000-000000000000

Reloaded:
John Doe (6ebacd17-f9ba-4ad8-9817-a5bb01112a5a)
   Points: 100
   HasGoldStatus: True
   MemberSince: 1/1/2012 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 42.4242

   Orders:
      Order Id: 16a6596b-d56e-41c7-9681-a5bb01112a60
      Order Id: d41d615b-0f21-4032-81db-a5bb01112a61
		
Press <ENTER> to exit...

Sekarang mari kita lihat Profiler NHibernate, Anda dapat melihat bahwa kita telah membuat join fetch yang bersemangat ini terjadi sekali lagi, tetapi kali ini, ini didasarkan pada kueri.

Dalam bab ini, kita akan membahas fitur lain yaitu Hubungan Invers. Ini adalah opsi lucu yang akan Anda lihat pada koleksi yang berbanding terbalik dengan true dan juga membingungkan banyak pengembang. Jadi mari kita bicara tentang opsi ini. Untuk memahami ini, Anda benar-benar harus memikirkan model relasional. Misalkan Anda memiliki asosiasi dua arah menggunakan kunci asing tunggal.

  • Dari sudut pandang relasional, Anda memiliki satu kunci asing, dan itu mewakili pelanggan untuk memesan dan memesan ke pelanggan.

  • Dari model OO, Anda memiliki asosiasi searah menggunakan referensi ini.

  • Tidak ada yang mengatakan bahwa dua asosiasi searah mewakili asosiasi dua arah yang sama dalam database.

  • Masalahnya di sini adalah NHibernate tidak memiliki cukup informasi untuk mengetahuinya customer.orders dan order.customer merepresentasikan hubungan yang sama dalam database.

  • Kami perlu menyediakan inverse equals true sebagai petunjuk, ini karena asosiasi searah menggunakan data yang sama.

  • Jika kami mencoba untuk menyimpan hubungan yang memiliki 2 referensi ke mereka, NHibernate akan mencoba memperbarui referensi itu dua kali.

  • Ini benar-benar akan melakukan perjalanan bolak-balik ekstra ke database, dan juga akan memiliki 2 pembaruan untuk kunci asing tersebut.

  • Pembalikan sama dengan true memberi tahu NHibernate sisi mana dari hubungan yang harus diabaikan.

  • Ketika Anda menerapkannya ke sisi koleksi dan NHibernate akan selalu memperbarui kunci asing dari sisi lain, dari sisi objek turunan.

  • Kemudian kami hanya memiliki satu pembaruan untuk kunci asing itu dan kami tidak memiliki pembaruan tambahan untuk data itu.

  • Hal ini memungkinkan kami untuk mencegah duplikasi pembaruan kunci asing ini dan juga membantu kami mencegah pelanggaran kunci asing.

Mari kita lihat customer.cs file di mana Anda akan melihat AddOrdermetode dan idenya di sini adalah bahwa kita sekarang memiliki penunjuk kembali ini dari pesanan kembali ke pelanggan dan perlu disetel. Jadi ketika pesanan ditambahkan ke pelanggan, penunjuk belakang pelanggan itu disetel, jika tidak, itu akan menjadi nol, jadi kita membutuhkan ini untuk tetap terhubung dengan benar bersama dalam grafik objek.

using System; 
using System.Text; 
using Iesi.Collections.Generic;

namespace NHibernateDemo {
 
   public class Customer { 
      
      public Customer() {
         MemberSince = DateTime.UtcNow; Orders = new HashedSet<Order>();
      } 
      
      public virtual Guid Id { get; set; } 
      public virtual string FirstName { get; set; } 
      public virtual string LastName { get; set; } 
      public virtual double AverageRating { get; set; } 
      public virtual int Points { get; set; } 
      public virtual bool HasGoldStatus { get; set; } 
		
      public virtual DateTime MemberSince { get; set; } 
      public virtual CustomerCreditRating CreditRating { get; set; } 
      public virtual Location Address { get; set; }
      public virtual ISet<Order> Orders { get; set; }
      public virtual void AddOrder(Order order) { Orders.Add(order); order.Customer = this; }
      
      public override string ToString() { 
         var result = new StringBuilder(); 
			
         result.AppendFormat("{1} {2} ({0})\r\n\tPoints: {3}\r\n\tHasGoldStatus:
            {4}\r\n\tMemberSince: {5} ({7})\r\n\tCreditRating: {6}\r\n\tAverageRating:
            {8}\r\n", Id, FirstName, LastName, Points, HasGoldStatus, MemberSince,
            CreditRating, MemberSince.Kind, AverageRating);
         result.AppendLine("\tOrders:"); 
         
         foreach(var order in Orders) { 
            result.AppendLine("\t\t" + order); 
         } 
			
         return result.ToString(); 
      } 
   }
   
   public class Location { 
      public virtual string Street { get; set; } 
      public virtual string City { get; set; } 
      public virtual string Province { get; set; } 
      public virtual string Country { get; set; }
   } 
   
   public enum CustomerCreditRating { 
      Excellent, 
      VeryVeryGood, 
      VeryGood, 
      Good, 
      Neutral, 
      Poor, 
      Terrible 
   } 
}

Ini dia Program.cs implementasi file.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Dialect; 
using NHibernate.Driver; 
using NHibernate.Linq;

namespace NHibernateDemo { 

   internal class Program { 
	
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         Guid id; 
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) { 
            var newCustomer = CreateCustomer(); 
            Console.WriteLine("New Customer:"); 
            Console.WriteLine(newCustomer); 
            session.Save(newCustomer); 
            id = newCustomer.Id;
            tx.Commit(); 
         }
         
         using(var session = sessionFactory.OpenSession())

         using(var tx = session.BeginTransaction()) { 
            var query = from customer in session.Query<Customer>() where
               customer.Id == id select customer; 
					
            var reloaded = query.Fetch(x => x.Orders).ToList().First();
            Console.WriteLine("Reloaded:"); Console.WriteLine(reloaded); 

            tx.Commit(); 
         }
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
      
      private static Customer CreateCustomer() { 
         var customer = new Customer { 
            FirstName = "John", 
            LastName = "Doe", 
            Points = 100, 
            HasGoldStatus = true, 
            MemberSince = new DateTime(2012, 1, 1), 
            CreditRating = CustomerCreditRating.Good, 
            AverageRating = 42.42424242, 
            Address = CreateLocation() 
         }; 
			
         var order1 = new Order { Ordered = DateTime.Now }; 
         
         customer.AddOrder(order1); var order2 = new Order {
            Ordered = DateTime.Now.AddDays(-1), 
            Shipped = DateTime.Now, 
            ShipTo = CreateLocation()
         }; 
			
         customer.AddOrder(order2); 
         return customer; 
      }
      
      private static Location CreateLocation() { 
         return new Location { 
            Street = "123 Somewhere Avenue", 
            City = "Nowhere", 
            Province = "Alberta", 
            Country = "Canada" 
         }; 
      }
      
      private static Configuration ConfigureNHibernate() { 
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10; 
            x.BatchSize = 10; 
         }); 
         
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Ini akan menyimpannya ke database dan kemudian memuatnya kembali. Sekarang mari kita jalankan aplikasi Anda dan buka NHibernate Profiler dan lihat bagaimana sebenarnya itu menyimpannya.

Anda akan melihat bahwa kami memiliki 3 kelompok pernyataan. Yang pertama akan memasukkan pelanggan, dan ID pelanggan itu adalah Panduan, yang disorot. Pernyataan kedua dimasukkan ke dalam tabel pesanan.

Anda akan melihat Panduan Id Pelanggan yang sama diatur di sana, jadi atur kunci asing itu. Pernyataan terakhir adalah pembaruan, yang akan memperbarui kunci asing ke id pelanggan yang sama sekali lagi.

Sekarang masalahnya adalah pelanggan memiliki pesanan, dan pesanan memiliki pelanggan, tidak mungkin kami belum memberi tahu NHibernate bahwa itu sebenarnya hubungan yang sama. Cara kita melakukannya adalah dengan invers sama dengan true.

Jadi mari kita pergi ke customer.hbm.xml file pemetaan dan atur inversi sama dengan true seperti yang ditunjukkan pada kode berikut.

<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo"
   namespace = "NHibernateDemo"> 
   
   <class name = "Customer">
	
      <id name = "Id"> 
         <generator class = "guid.comb"/> 
      </id> 
      
      <property name = "FirstName"/> 
      <property name = "LastName"/> 
      <property name = "AverageRating"/> 
      <property name = "Points"/> 
      <property name = "HasGoldStatus"/> 
      <property name = "MemberSince" type = "UtcDateTime"/>
      <property name = "CreditRating" type = "CustomerCreditRatingType"/>
      
      <component name = "Address"> 
         <property name = "Street"/> 
         <property name = "City"/> 
         <property name = "Province"/> 
         <property name = "Country"/> 
      </component>
      
      <set name = "Orders" table = "`Order`" cascade = "all-delete-orphan" 
         inverse = "true"> 
         <key column = "CustomerId"/> 
         <one-to-many class = "Order"/> 
      </set> 
   
   </class> 
</hibernate-mapping>

Saat menyimpan pesanan, itu akan mengatur kunci asing itu dari sisi pesanan. Sekarang mari kita jalankan aplikasi ini lagi dan buka profiler NHibernate.

Jika kita melihat bagaimana mereka disisipkan, kita mendapatkan sisipan di pelanggan, dan sisipkan ke dalam pesanan, tapi kita tidak memiliki pembaruan duplikat dari kunci asing karena sedang diperbarui ketika pesanan disimpan.

  • Sekarang, Anda harus mencatat bahwa jika Anda hanya memiliki asosiasi searah dan himpunanlah yang mempertahankan hubungan ini, maka jika Anda mengubah invers sama dengan true, kunci asing itu tidak akan pernah disetel, dan item tersebut tidak akan pernah memiliki kunci asing diatur dalam database.

  • Jika Anda melihat hubungan banyak-ke-satu di file Order.hbm.xml file dan Anda mencari invers, itu sebenarnya tidak memiliki atribut invers.

  • Itu selalu disetel dari item anak, tetapi jika Anda memiliki koleksi banyak-ke-banyak, Anda dapat menyetelnya dari kedua sisi.

Dalam bab ini, kita akan membahas bagaimana fitur Muat dan Dapatkan bekerja dan bagaimana kita dapat menggunakannya. Ini adalah dua API yang sangat mirip yang disediakan olehISession untuk memuat objek dengan kunci utama.

  • Get - itu akan mengembalikan objek atau nol.

  • Load - itu akan mengembalikan objek atau akan melempar ObjectNotFoundException.

Sekarang, mengapa kita memiliki dua API yang berbeda ini?

Beban

  • Itu karena Load dapat mengoptimalkan perjalanan bolak-balik database dengan jauh lebih efisien.

  • Load sebenarnya mengembalikan objek proxy dan tidak perlu mengakses database tepat saat Anda mengeluarkan panggilan Load itu.

  • Saat Anda mengakses proxy itu, objek tersebut tidak kebetulan ada di database, itu bisa melempar ObjectNotFoundException pada saat itu.

Dapatkan

  • Sebaliknya, dengan Get karena keterbatasan CLR atau Common Language Runtime dan NHibernate harus segera pergi ke database, memeriksa apakah objek ada dan mengembalikan null, jika tidak ada.

  • Ia tidak memiliki opsi objek untuk menunda pengambilan itu, bolak-balik itu ke database di lain waktu karena tidak dapat mengembalikan objek proxy dan menukar objek proxy itu dengan null, saat pengguna benar-benar mengaksesnya.

Mari kita lihat contoh sederhana di mana Anda akan melihat bagaimana ini sebenarnya digunakan dan perbedaan antara Get dan Load. Kami akan melanjutkan dengan kelas domain yang samaCustomers dan Orders dan juga file pemetaan yang sama dari bab terakhir.

Dalam contoh ini, pertama-tama kami akan menggunakan Get seperti yang ditunjukkan pada program berikut.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver;
using NHibernate.Linq; 

namespace NHibernateDemo { 

   internal class Program { 
	
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) { 
            var id1 = Guid.Parse("4e97c816-6bce-11e1-b095-6cf049ee52be"); 
            var id2 = Guid.Parse("AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE");
				
            var customer1 = session.Get<Customer>(id1); 
            Console.WriteLine("Customer1 data"); 
            Console.WriteLine(customer1);
				
            var customer2 = session.Get<Customer>(id2); 
            Console.WriteLine("Customer2 data"); 
            Console.WriteLine(customer2); 
				
            tx.Commit(); 
         }
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
		
      private static Configuration ConfigureNHibernate() {
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead;
            x.Timeout = 10; 
            x.BatchSize = 10; 
         }); 
         
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Seperti yang Anda lihat, kami memiliki dua GuidID, yang pertama adalah ID yang bagus, itu adalah ID pelanggan yang kita tahu ada di database. Sedangkan ID kedua tidak ada di database. Kedua ID ini diteruskan sebagai parameter keGet() metode dan kemudian hasilnya dicetak di konsol.

Ketika kode di atas dikompilasi dan dijalankan Anda akan melihat output berikut.

Customer1 data
Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
   Points: 74
   HasGoldStatus: True
   MemberSince: 4/4/2009 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

Orders:
   Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
   Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
   Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
   Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be
	
Customer2 data
Press <ENTER> to exit...

Seperti yang Anda lihat bahwa data Pelanggan1 dicetak tetapi data Pelanggan2 kosong, itu karena catatan Pelanggan2 tidak tersedia dalam database.

Saat Anda menjalankan aplikasi Anda lagi, kita dapat memasukkan sebuah break point sebelum pernyataan commit dan kemudian mari kita lihat kedua pelanggan di jendela Watch.

Seperti yang Anda lihat bahwa data Pelanggan1 tersedia, sedangkan Pelanggan2 adalah null dan tipenya adalah NHibernateDemo.Customer untuk keduanya.

Sekarang mari gunakan metode Muat alih-alih Dapatkan dalam contoh yang sama seperti yang ditunjukkan pada kode berikut.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver;
using NHibernate.Linq; 

namespace NHibernateDemo { 

   internal class Program { 
	
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) { 
            var id1 = Guid.Parse("4e97c816-6bce-11e1-b095-6cf049ee52be"); 
            var id2 = Guid.Parse("AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE");
				
            var customer1 = session.Load<Customer>(id1); 
            Console.WriteLine("Customer1 data"); 
            Console.WriteLine(customer1);
				
            var customer2 = session.Load<Customer>(id2); 
            Console.WriteLine("Customer2 data"); 
            Console.WriteLine(customer2); 
				
            tx.Commit(); 
         }
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
		
      private static Configuration ConfigureNHibernate() { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10;
            x.BatchSize = 10; 
         }); 
			
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Sekarang mari kita jalankan contoh ini dan Anda akan melihat bahwa pengecualian berikut ditampilkan seperti yang terlihat pada tangkapan layar.

Sekarang jika Anda melihat pada jendela Watch, Anda akan melihat tipe adalah proxy pelanggan untuk kedua objek. Dan Anda juga melihat data yang sama untuk Pelanggan1 di jendela konsol.

Customer1 data
Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
   Points: 74
   HasGoldStatus: True
   MemberSince: 4/4/2009 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be 
		
Customer2 data

Dalam bab ini, kami akan membahas API umum lainnya yang akan digunakan orang adalah penyedia LINQ NHibernate. Aksesnya melalui metode ekstensi pada ISession dan tandatangannya adalah aQuery <T>. Ada dua jenis sintaks saat menggunakan LINQ -

  • Query Chaining Syntax
  • Sintaks Pemahaman Kueri

Query Chaining Syntax

Anda dapat mengakses rekaman apa pun dari database menggunakan sintaks rantai metode seperti yang ditunjukkan dalam program berikut.

var customer = session.Query<Customer>() .Where(c => c.FirstName == "Laverne")
  • Anda dapat melihat bahwa kami memiliki kueri, dan juga klausa WHERE, Anda dapat memiliki klausa WHERE tambahan dan juga memilih klausa.

  • Ini adalah sintaks rantai metode standar yang dapat Anda gunakan di LINQ normal.

  • LINQ ke Objek atau LINQ ke SQL, salah satu penyedia LINQ lain yang mungkin Anda kenal.

Mari kita lihat contoh sederhana di mana kita akan mengambil pelanggan yang nama depannya adalah Laverne. Sekarang ada kemungkinan bahwa kami mungkin memiliki lebih dari satu pelanggan dengan nama depan Laverne, jadi kami hanya akan mengambil yang pertama.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver; 
using NHibernate.Linq;

namespace NHibernateDemo { 

   internal class Program {
	
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) {
            var customer = session.Query<Customer>() 
               .Where(c => c.FirstName == "Laverne").First(); 
            Console.WriteLine(customer); 
            tx.Commit(); 
         }
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
		
      private static Configuration ConfigureNHibernate() { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10; 
            x.BatchSize = 10; 
         }); 
         
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Sekarang ketika kode di atas dikompilasi dan dijalankan, Anda akan melihat output berikut.

Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
   Points: 74
   HasGoldStatus: True
   MemberSince: 4/4/2009 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be
		
Press <ENTER> to exit...

Sintaks Pemahaman Kueri

Ada juga sintaks pemahaman kueri, yang lebih mirip SQL menggunakan kata kunci from, where, dan select.

Jadi mari kita lihat contoh yang sama, tapi kali ini kita menggunakan sintaks pemahaman LINQ, yang lebih mirip SQL seperti yang ditunjukkan pada program berikut.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver; 
using NHibernate.Linq;

namespace NHibernateDemo { 

   internal class Program { 
	
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) {
            var customer = (from c in session.Query<Customer>() 
               where c.FirstName == "Laverne" select c).First();
            Console.WriteLine(customer); 
            tx.Commit();
         }
         
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
      
      private static Configuration ConfigureNHibernate() {
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10; 
            x.BatchSize = 10; 
         }); 
         
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Sekarang mari kita jalankan aplikasi ini lagi dan Anda akan melihat output berikut.

Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
   Points: 74
   HasGoldStatus: True
   MemberSince: 4/4/2009 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be
		
Press <ENTER> to exit...

Mari kita lihat contoh lain di mana kita akan mengambil semua pelanggan tersebut, yang Nama Depannya dimulai dengan huruf H.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver; 
using NHibernate.Linq;

namespace NHibernateDemo { 

   internal class Program { 
	
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) {
            var customers = session.Query<Customer>() .Where(c =<
               c.FirstName.StartsWith("H"));
            
            foreach (var customer in customers.ToList()) { 
               Console.WriteLine(customer); 
            }
				
            tx.Commit(); 
         }
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
		
      private static Configuration ConfigureNHibernate() { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10; 
            x.BatchSize = 10; 
         }); 
			
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Demikian pula, sintaks pemahaman kueri akan terlihat seperti program berikut.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver; 
using NHibernate.Linq;

namespace NHibernateDemo { 

   internal class Program { 
	
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) {
            var customers = from c in session.Query<Customer>() 
               where c.FirstName.StartsWith("H") select c;
            
            foreach (var customer in customers.ToList()) { 
               Console.WriteLine(customer); 
            }
				
            tx.Commit(); 
         }
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
		
      private static Configuration ConfigureNHibernate() { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10; 
            x.BatchSize = 10; 
         }); 
			
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   }  
}

Ayo jalankan aplikasi ini lagi dan Anda akan melihat semua pelanggan, yang nama depannya diawali dengan abjad H.

Herman Crooks (4ead3480-6bce-11e1-b15c-6cf049ee52be)
   Points: 74
   HasGoldStatus: True
   MemberSince: 12/3/2010 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ead3480-6bce-11e1-b15d-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b15e-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b15f-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b160-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b161-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b162-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b163-6cf049ee52be

Hudson Bins (4ec03f80-6bce-11e1-b2b7-6cf049ee52be)
   Points: 56
   HasGoldStatus: False
   MemberSince: 10/20/2008 12:00:00 AM (Utc)
   CreditRating: Terrible
   AverageRating: 0

   Orders:
      Order Id: 4ec03f80-6bce-11e1-b2b8-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2b9-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2ba-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2bb-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2bc-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2bd-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2be-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2bf-6cf049ee52be

Hettie Feest (4ec50240-6bce-11e1-b300-6cf049ee52be)
   Points: 82
   HasGoldStatus: False
   MemberSince: 4/10/2009 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ec50240-6bce-11e1-b301-6cf049ee52be
      Order Id: 4ec50240-6bce-11e1-b302-6cf049ee52be
      Order Id: 4ec50240-6bce-11e1-b303-6cf049ee52be
		
Press <ENTER> to exit...

Dalam bab ini, kami akan membahas Bahasa Query Hibernate. HQL digunakan bersama oleh Java Hibernate dan NHibernate.

  • Ini adalah mekanisme kueri tertua bersama Criteria.

  • Ini diterapkan sangat awal dan merupakan kueri berbasis string API.

  • Anda mengaksesnya melalui ISession CreateQuery, dan hampir mirip dengan SQL.

  • Ini menggunakan banyak kata kunci yang sama, tetapi memiliki sintaks yang disederhanakan.

  • Ini adalah salah satu contoh paling umum, jika Anda mencari cara melakukan kueri, Anda akan sering menemukan contoh HQL.

Berikut ini adalah contoh sederhana dari HQL -

var customers = session.CreateQuery("select c from Customer c where c.FirstName = 'Laverne'");
  • Jadi di sini Anda dapat melihat bahwa mereka memilih C dari pelanggan, sangat mirip dengan SQL. Ini adalah string buram sejauh menyangkut NHibernate, jadi Anda tidak tahu apakah ini HQL yang valid hingga runtime, yang merupakan salah satu kelemahannya.

  • Salah satu kekuatan penyedia LINQ adalah Anda dapat mengumpulkan dukungan waktu.

  • Tapi HQL, adalah salah satu mekanisme kueri paling fleksibel yang sering digunakan. Dikatakan bahwa, jika tidak ada cara lain untuk melakukannya maka ada cara untuk melakukannya di HQL.

Mari kita lihat contoh simpe di mana kami akan membuat ulang kueri LINQ kami menggunakan HQL sebagai gantinya. Anda bisa mendapatkan akses ke HQL dengan memanggilsession.CreateQuery dan lulus sebagai parameter menggunakan string HQL.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver; 
using NHibernate.Linq;

namespace NHibernateDemo {

   internal class Program { 
      
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) { 
            var customers = session.CreateQuery("select c from Customer c 
               where c.FirstName = 'Laverne'"); 
            
            foreach (var customer in customers.List<Customer>()) { 
               Console.WriteLine(customer); 
            }
				
            tx.Commit(); 
         }
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
		
      private static Configuration ConfigureNHibernate() { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10; 
            x.BatchSize = 10; 
         }); 
         
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}
  • String HQL ini sangat mirip dengan SQL, perbedaan utamanya adalah FirstName adalah nama properti dan bukan nama kolom.

  • Jadi, jika ada perbedaan di antara keduanya, gunakan nama properti. Hal yang sama, terlihat seperti nama tabel, tetapi sebenarnya itu adalah nama kelas yang kita pilih.

  • Jika tabel back end dinamai sebagai Pelanggan, kami masih akan menggunakan Pelanggan dalam kueri HQL kami.

Ayo jalankan aplikasi ini dan Anda akan melihat output berikut.

Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
   Points: 74
   HasGoldStatus: True
   MemberSince: 4/4/2009 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be
		
Press <ENTER> to exit...

Mari kita lihat contoh sederhana lainnya di mana kita akan mengambil semua pelanggan yang Nama Depannya dimulai dengan huruf H menggunakan HQL.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver;
using NHibernate.Linq; 

namespace NHibernateDemo { 

   internal class Program {
	
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) { 
            var customers = session.CreateQuery("select c from Customer c 
               where c.FirstName like 'H%'"); 
            
            foreach (var customer in customers.List<Customer>()) { 
               Console.WriteLine(customer); 
            }
				
            tx.Commit(); 
         } 
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      } 
		
      private static Configuration ConfigureNHibernate() {
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10; 
            x.BatchSize = 10; 
         }); 
			
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Jalankan aplikasi Anda lagi dan Anda akan melihat bahwa semua pelanggan yang namanya dimulai dengan H dikembalikan dari kueri ini.

Herman Crooks (4ead3480-6bce-11e1-b15c-6cf049ee52be)
   Points: 74
   HasGoldStatus: True
   MemberSince: 12/3/2010 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ead3480-6bce-11e1-b15d-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b15e-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b15f-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b160-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b161-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b162-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b163-6cf049ee52be

Hudson Bins (4ec03f80-6bce-11e1-b2b7-6cf049ee52be)
   Points: 56
   HasGoldStatus: False
   MemberSince: 10/20/2008 12:00:00 AM (Utc)
   CreditRating: Terrible
   AverageRating: 0

   Orders:
      Order Id: 4ec03f80-6bce-11e1-b2b8-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2b9-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2ba-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2bb-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2bc-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2bd-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2be-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2bf-6cf049ee52be

Hettie Feest (4ec50240-6bce-11e1-b300-6cf049ee52be)
   Points: 82
   HasGoldStatus: False
   MemberSince: 4/10/2009 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ec50240-6bce-11e1-b301-6cf049ee52be
      Order Id: 4ec50240-6bce-11e1-b302-6cf049ee52be
      Order Id: 4ec50240-6bce-11e1-b303-6cf049ee52be
		
Press <ENTER> to exit...

Kita dapat melakukan hal-hal yang lebih rumit seperti menginginkan semua pesanan di mana pelanggan dengan jumlah pesanan lebih besar dari 9. Berikut adalah kueri HQL yang sama.

var customers = session.CreateQuery("select c from Customer c 
   where size(c.Orders) > 9"); 
	
foreach (var customer in customers.List<Customer>()) { 
   Console.WriteLine(customer); 
}

Kami juga perlu menunjukkan bahwa kami membutuhkan ukuran di sini atau hitungan atau panjang. Di HQL, kami memiliki opsi untuk menggunakan metode ukuran khusus seperti yang ditunjukkan di atas.

Cara lain untuk menulis ini, jika Anda mau adalah c.Orders.size, dan ini memiliki efek yang sama persis.

var customers = session.CreateQuery("select c from Customer c 
   where c.Orders.size > 9"); 
	
foreach (var customer in customers.List<Customer>()) { 
   Console.WriteLine(customer); 
}

Ayo jalankan aplikasi ini.

Lindsay Towne (4ea3aef6-6bce-11e1-b0cb-6cf049ee52be)
   Points: 50
   HasGoldStatus: False
   MemberSince: 4/13/2007 12:00:00 AM (Utc)
   CreditRating: VeryGood
   AverageRating: 0

   Orders:
      Order Id: 4ea3aef6-6bce-11e1-b0cc-6cf049ee52be
      Order Id: 4ea3aef6-6bce-11e1-b0cd-6cf049ee52be
      Order Id: 4ea3aef6-6bce-11e1-b0ce-6cf049ee52be
      Order Id: 4ea3aef6-6bce-11e1-b0cf-6cf049ee52be
      Order Id: 4ea3aef6-6bce-11e1-b0d0-6cf049ee52be
      Order Id: 4ea3aef6-6bce-11e1-b0d1-6cf049ee52be
      Order Id: 4ea3aef6-6bce-11e1-b0d2-6cf049ee52be
      Order Id: 4ea3aef6-6bce-11e1-b0d3-6cf049ee52be
      Order Id: 4ea3aef6-6bce-11e1-b0d4-6cf049ee52be
      Order Id: 4ea3aef6-6bce-11e1-b0d5-6cf049ee52be

Wyman Hammes (4ea61056-6bce-11e1-b0e2-6cf049ee52be)
   Points: 32
   HasGoldStatus: False
   MemberSince: 2/5/2011 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 0

   Orders:
      Order Id: 4ea61056-6bce-11e1-b0e3-6cf049ee52be
      Order Id: 4ea61056-6bce-11e1-b0e4-6cf049ee52be
      Order Id: 4ea61056-6bce-11e1-b0e5-6cf049ee52be
      Order Id: 4ea61056-6bce-11e1-b0e6-6cf049ee52be
      Order Id: 4ea61056-6bce-11e1-b0e7-6cf049ee52be
      Order Id: 4ea61056-6bce-11e1-b0e8-6cf049ee52be
      Order Id: 4ea61056-6bce-11e1-b0e9-6cf049ee52be
      Order Id: 4ea61056-6bce-11e1-b0ea-6cf049ee52be
      Order Id: 4ea61056-6bce-11e1-b0eb-6cf049ee52be
      Order Id: 4ea61056-6bce-11e1-b0ec-6cf049ee52be
		
Press <ENTER> to exit...

Anda dapat melihat bahwa semua pelanggan, yang memiliki lebih dari 9 pesanan diambil dari database.

Dalam bab ini, kita akan membahas mekanisme query kriteria. ItuNHibernate Query by Criteria API memungkinkan Anda membuat kueri dengan memanipulasi objek kriteria pada waktu proses.

  • Pendekatan ini memungkinkan Anda menentukan batasan secara dinamis tanpa manipulasi string langsung, tetapi tidak kehilangan banyak fleksibilitas atau kekuatan HQL.

  • Di sisi lain, kueri yang dinyatakan sebagai kriteria seringkali kurang dapat dibaca daripada kueri yang dinyatakan dalam HQL.

  • Sintaks kriteria klasik adalah API kueri berbasis objek seperti yang ditunjukkan dalam program berikut.

var customers = session.CreateCriteria<Customer>().Add(Restrictions.Like("FirstName", "H%"));
  • Seperti yang Anda lihat, kami sedang melakukan sesi membuat kriteria pada pelanggan, dan sekarang kami menambahkan objek pembatasan ke kueri itu.

  • Ini berguna untuk halaman kueri tempat pengguna dapat memilih opsi tertentu, tetapi tidak yang lain.

  • Lebih mudah untuk membangun kueri sebagai semacam pohon seperti struktur kueri daripada di HQL atau LINQ, di mana Anda dapat menggunakan klausa AND atau OR di WHERE.

  • Lebih mudah untuk menambahkan batasan tambahan menggunakan objek kriteria ini.

Mari kita lihat contoh sederhana di mana kita akan membuat kueri dan mendapatkan akses ke API kriteria createCriteria lalu tambahkan batasan bahwa nama depan dimulai dengan H.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver; 
using NHibernate.Linq; 

namespace NHibernateDemo {

   internal class Program { 
      
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) { 
            var customers = session.CreateCriteria<Customer>() 
               .Add(Restrictions.Like("FirstName", "H%")); 
         
            foreach (var customer in customers.List<Customer>()) { 
               Console.WriteLine(customer); 
            } 
				
            tx.Commit(); 
         }
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      } 
		
      private static Configuration ConfigureNHibernate() {
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10; 
            x.BatchSize = 10; 
         }); 
			
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Ketika kode di atas dikompilasi dan dijalankan Anda akan melihat output berikut.

Herman Crooks (4ead3480-6bce-11e1-b15c-6cf049ee52be)
   Points: 74
   HasGoldStatus: True
   MemberSince: 12/3/2010 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ead3480-6bce-11e1-b15d-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b15e-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b15f-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b160-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b161-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b162-6cf049ee52be
      Order Id: 4ead3480-6bce-11e1-b163-6cf049ee52be

Hudson Bins (4ec03f80-6bce-11e1-b2b7-6cf049ee52be)
   Points: 56
   HasGoldStatus: False
   MemberSince: 10/20/2008 12:00:00 AM (Utc)
   CreditRating: Terrible
   AverageRating: 0

   Orders:
      Order Id: 4ec03f80-6bce-11e1-b2b8-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2b9-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2ba-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2bb-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2bc-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2bd-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2be-6cf049ee52be
      Order Id: 4ec03f80-6bce-11e1-b2bf-6cf049ee52be

Hettie Feest (4ec50240-6bce-11e1-b300-6cf049ee52be)
   Points: 82
   HasGoldStatus: False
   MemberSince: 4/10/2009 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ec50240-6bce-11e1-b301-6cf049ee52be
      Order Id: 4ec50240-6bce-11e1-b302-6cf049ee52be
      Order Id: 4ec50240-6bce-11e1-b303-6cf049ee52be
		
Press <ENTER> to exit…

Mari kita lihat contoh sederhana lainnya di mana kita akan mengambil pelanggan yang nama depannya sama dengan "Laverne"

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver; 
using NHibernate.Linq;

namespace NHibernateDemo { 

   internal class Program { 
      
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
			
         using(var tx = session.BeginTransaction()) { 
            var customers = session.CreateCriteria<Customer>() 
               .Add(Restrictions.Eq("FirstName", "Laverne")) .List<Customer>(); 
            
            foreach (var customer in customers) {
               Console.WriteLine(customer); 
            } 
				
            tx.Commit(); 
         }
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
		
      private static Configuration ConfigureNHibernate() {
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10; 
            x.BatchSize = 10; 
         }); 
         
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Jalankan aplikasi ini lagi dan Anda akan melihat output berikut.

Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
   Points: 74
   HasGoldStatus: True
   MemberSince: 4/4/2009 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be
		
Press <ENTER> to exit...

Sekarang, salah satu kelemahan utama dari API kriteria adalah string buram ini dalam nama properti. Jadi, jika nama depan difaktor ulang menjadi sesuatu yang lain, alat pemfaktoran ulang tidak akan mengambil string buram.

Di bab ini, kita akan membahas QueryOver Queries. Ini adalah sintaks baru yang lebih seperti LINQ menggunakan sintaks rantai metode seperti yang ditunjukkan pada kueri berikut.

var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "Laverne");
  • Ini masih kriteria di bawah sampul, tetapi sekarang kueri kami sangat diketik.

  • Seperti yang telah kita lihat di kueri kriteria, nama depan hanyalah string buram, sekarang kita sebenarnya menggunakan x.FirstName, sehingga nama depan difaktorkan ulang dan diganti namanya yang diubah dalam kueri kriteria gaya tautan menggunakan kueri di atas.

  • Kami masih dapat melakukan banyak hal serupa, tetapi Anda tidak dapat menggunakan sintaks pemahaman kueri dengan kueri berakhir, Anda harus menggunakan sintaks rantai metode dan Anda tidak dapat mencampur dan mencocokkan tautan dan kriteria.

  • Untuk banyak kueri, kueri melalui API sangat berguna dan menyediakan sintaks objek yang jauh lebih mudah dipahami daripada menggunakan Kriteria secara langsung.

Mari kita lihat contoh sederhana di mana kita akan mengambil pelanggan yang nama depannya adalah Laverne menggunakan kueri.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver; 
using NHibernate.Linq;

namespace NHibernateDemo { 

   internal class Program { 
      
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) { 
            var customers = session.QueryOver<Customer>() 
               .Where(x => x.FirstName == "Laverne"); 
            
            foreach (var customer in customers.List()) { 
               Console.WriteLine(customer); 
            } 
				
            tx.Commit(); 
         }
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
      
      private static Configuration ConfigureNHibernate() { 
		
         NHibernateProfiler.Initialize();
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10; 
            x.BatchSize = 10; 
         });
			
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Seperti yang Anda lihat, ini masih Kriteria di bawah sampul, tetapi hanya sintaks yang lebih bagus.

Ketika kode di atas dikompilasi dan dijalankan, Anda akan melihat output berikut.

Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
   Points: 74
   HasGoldStatus: True
   MemberSince: 4/4/2009 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be
		
Press <ENTER> to exit...

Salah satu kekurangannya adalah, katakanlah kita ingin mengatakan itu FirstName.StartsWith(“A”) seperti yang ditunjukkan pada program berikut.

var customers = session.QueryOver<Customer>() .Where(x => x.FirstName.StartsWith("A"));
 
foreach (var customer in customers.List()) { 
   Console.WriteLine(customer); 
} 

tx.Commit();

Sekarang mari jalankan aplikasi lagi dan Anda akan melihat bahwa ini bukan penyedia LINQ karena tidak tahu apa ini StartsWith metode ini, jadi Anda akan mendapatkan file RunTime exception.

Pengecualian mengatakan panggilan metode tidak dikenal. Di sini kami melakukan hal yang jelas, tetapi belum tentu berhasil.

Mari kita coba yang lain, seperti FirstName sama dengan "A%" seperti yang ditunjukkan pada kode berikut.

var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "A%"); 

foreach (var customer in customers.List()) { 
   Console.WriteLine(customer); 
}

Mari kita jalankan ini sekali lagi dan Anda akan melihat bahwa kami tidak akan mendapatkan hasil apa pun kembali seperti yang ditunjukkan di bawah ini.

Press <ENTER> to exit...

Untuk memahami mengapa kami tidak mendapatkan hasil apa pun, mari kita lihat profiler NHibernate.

Seperti yang Anda lihat bahwa nama depan sama dengan A% yang bukan. A% digunakan dalam SQL menggunakan operator sejenis. Sekarang kita perlu membuat batasan ke klausa WHERE seperti yang ditunjukkan pada program berikut.

var customers = session.QueryOver<Customer>() 
   .Where(Restrictions.On<Customer>(c => c.FirstName).IsLike("A%")); 
	
foreach (var customer in customers.List()) { 
   Console.WriteLine(customer); 
}

Jalankan aplikasi Anda lagi dan Anda akan melihat bahwa semua pelanggan diambil dengan nama depan dimulai dengan A.

Alejandrin Will (4ea3aef6-6bce-11e1-b0b4-6cf049ee52be)
   Points: 24
   HasGoldStatus: False
   MemberSince: 10/1/2011 12:00:00 AM (Utc)
   CreditRating: VeryVeryGood
   AverageRating: 0

   Orders:
      Order Id: 4ea3aef6-6bce-11e1-b0b5-6cf049ee52be

Austyn Nolan (4ea871b6-6bce-11e1-b110-6cf049ee52be)
   Points: 67
   HasGoldStatus: True
   MemberSince: 12/29/2007 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ea871b6-6bce-11e1-b111-6cf049ee52be

Antonia Murphy (4ea871b6-6bce-11e1-b121-6cf049ee52be)
   Points: 72
   HasGoldStatus: True
   MemberSince: 6/15/2009 12:00:00 AM (Utc)
   CreditRating: Terrible
   AverageRating: 0

   Orders:
      Order Id: 4ea871b6-6bce-11e1-b122-6cf049ee52be
      Order Id: 4ea871b6-6bce-11e1-b123-6cf049ee52be
      Order Id: 4ea871b6-6bce-11e1-b124-6cf049ee52be
      Order Id: 4ea871b6-6bce-11e1-b125-6cf049ee52be
      Order Id: 4ea871b6-6bce-11e1-b126-6cf049ee52be
      Order Id: 4ea871b6-6bce-11e1-b127-6cf049ee52be
      Order Id: 4ea871b6-6bce-11e1-b128-6cf049ee52be
      Order Id: 4ea871b6-6bce-11e1-b129-6cf049ee52be
      Order Id: 4ea871b6-6bce-11e1-b12a-6cf049ee52be

Ini bekerja dengan cara yang sama seperti sebelumnya, kecuali menggunakan yang baru ini QueryOversintaksis. Banyak pengembang menemukan bahwa sintaks LINQ lebih mudah didekati dan sering melakukan hal yang benar.

Jika LINQ tidak dapat mengatasinya, maka Anda akan mulai melihat HQL atau Kriteria untuk melihat apakah itu lebih cocok.

Ini hanya memberi Anda sintaks yang berbeda, jadi Criteria, baik kriteria create maupun QueryOver memberi Anda mekanisme kueri lain yang memungkinkan Anda untuk menarik data keluar dari database menggunakan NHibernate.

Dalam bab ini, kami akan membahas cara menggunakan kueri SQL asli di NHibernate. Jika Anda telah menggunakan SQL tulisan tangan selama beberapa tahun, Anda mungkin khawatir bahwa ORM akan menghilangkan beberapa ekspresi dan fleksibilitas yang biasa Anda gunakan.

  • Fasilitas query NHibernate yang kuat memungkinkan Anda melakukan hampir semua hal yang Anda lakukan dalam SQL, dan dalam beberapa kasus lebih.

  • Untuk kasus yang jarang terjadi di mana Anda tidak dapat membuat fasilitas kueri NHibernate melakukan apa yang Anda inginkan.

  • NHibernate memungkinkan Anda mengambil objek menggunakan dialek SQL asli database Anda.

Mari kita lihat contoh sederhana dari kueri SQL Asli di NHibernate.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver; 
using NHibernate.Linq; 
using NHibernate;

namespace NHibernateDemo {

   internal class Program { 
	
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) {
            IQuery sqlQuery = session.CreateSQLQuery("SELECT * FROM
               CUSTOMER").AddEntity(typeof(Customer));
            var customers = sqlQuery.List<Customer>();
				
            foreach (var customer in customers) { 
               Console.WriteLine(customer); 
            } 
				
            tx.Commit(); 
         }
         
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
		
      private static Configuration ConfigureNHibernate() { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10; 
            x.BatchSize = 10; 
         }); 
         
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Contoh di atas menggunakan CreateSQLQuery() untuk mendapatkan kembali daftar objek, dan Anda juga akan melihat bahwa tipe entitas akar yang Anda inginkan untuk kembalikan ditetapkan sebagai Pelanggan.

Jalankan aplikasi Anda dan Anda akan melihat bahwa semua pelanggan diambil dari database.

Emerson Prosacco (4ec2a0e0-6bce-11e1-b2cf-6cf049ee52be)
   Points: 17
   HasGoldStatus: False
   MemberSince: 6/22/2007 12:00:00 AM (Utc)
   CreditRating: Excellent
   AverageRating: 0

   Orders:
      Order Id: 4ec2a0e0-6bce-11e1-b2d0-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2d1-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2d2-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2d3-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2d4-6cf049ee52be

Kaci Friesen (4ec2a0e0-6bce-11e1-b2d5-6cf049ee52be)
   Points: 30
   HasGoldStatus: True
   MemberSince: 5/25/2007 12:00:00 AM (Utc)
   CreditRating: VeryVeryGood
   AverageRating: 0

   Orders:
      Order Id: 4ec2a0e0-6bce-11e1-b2d6-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2d7-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2d8-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2d9-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2da-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2db-6cf049ee52be

Eveline Waters (4ec2a0e0-6bce-11e1-b2dc-6cf049ee52be)
   Points: 58
   HasGoldStatus: False
   MemberSince: 10/29/2009 12:00:00 AM (Utc)
   CreditRating: Good
   AverageRating: 0

   Orders:
      Order Id: 4ec2a0e0-6bce-11e1-b2dd-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2de-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2df-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2e0-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2e2-6cf049ee52be

Molly Kuhn (4ec2a0e0-6bce-11e1-b2e3-6cf049ee52be)
   Points: 73
   HasGoldStatus: False
   MemberSince: 12/16/2007 12:00:00 AM (Utc)
   CreditRating: VeryGood
   AverageRating: 0

   Orders:
      Order Id: 4ec2a0e0-6bce-11e1-b2e4-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2e5-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2e6-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2e7-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2e8-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2e9-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2ea-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2eb-6cf049ee52be
      Order Id: 4ec2a0e0-6bce-11e1-b2ec-6cf049ee52be

Berikut adalah cara lain untuk menulis kueri SQL asli seperti yang ditunjukkan di bawah ini.

IList<Customer> customers = session.CreateSQLQuery("SELECT * FROM CUSTOMER")
   .AddScalar("Id", NHibernateUtil.Guid) 
   .AddScalar("FirstName", NHibernateUtil.String) 
   .AddScalar("LastName", NHibernateUtil.String) .List<Customer>();
  • Seperti yang Anda lihat bahwa kueri di atas menentukan string kueri SQL dan kolom serta tipe yang akan dikembalikan.

  • Ini akan mengembalikan IList array Object dengan nilai skalar untuk setiap kolom di tabel Customer.

  • Hanya tiga kolom ini yang akan dikembalikan, meskipun kueri menggunakan * dan dapat mengembalikan lebih dari tiga kolom yang terdaftar.

Mari kita lihat contoh sederhana lainnya.

IList<Customer> customers = session.CreateSQLQuery("SELECT * FROM CUSTOMER WHERE  
   FirstName = 'Laverne'") 
   .AddEntity(typeof(Customer)) .List<Customer>(); 
	
foreach (var customer in customers) { 
   Console.WriteLine(customer); 
}

Jalankan aplikasi Anda lagi dan Anda akan melihat output berikut.

Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
   Points: 74
   HasGoldStatus: True
   MemberSince: 4/4/2009 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be
		
Press <ENTER> to exit...

Demikian pula, Anda bisa menentukan tipe kueri SQL apa pun untuk mengambil data dari database.

Dalam bab ini, kami akan membahas NHibernate yang lancar. Fluent NHibernate adalah cara lain untuk memetakan atau Anda bisa menyebutnya sebagai alternatif dari file pemetaan XML standar NHibernate. Alih-alih menulis XML(.hbm.xml files)dokumen. Dengan bantuan Fluent NHibernate, Anda dapat menulis pemetaan dalam kode C # yang diketik dengan kuat.

  • Dalam pemetaan Fluent NHibernate dikompilasi bersama dengan aplikasi Anda lainnya.

  • Anda dapat dengan mudah mengubah pemetaan seperti kode aplikasi Anda dan kompilator akan gagal jika salah ketik.

  • Ini memiliki sistem konfigurasi konvensional, di mana Anda dapat menentukan pola untuk mengganti konvensi penamaan dan banyak hal lainnya.

  • Anda juga dapat mengatur bagaimana sesuatu harus diberi nama satu kali, kemudian Fluent NHibernate mengerjakan sisanya.

Mari kita lihat contoh sederhana dengan membuat proyek konsol baru. Dalam bab ini, kita akan menggunakan database sederhana di mana kita memiliki tabel Pelanggan sederhana seperti yang ditunjukkan pada gambar berikut.

Instal Fluent NHibernate

Langkah pertama untuk memulai Fluent NHibernate adalah menginstal paket Fluent NHibernate. Jadi bukaNuGet Package Manager Console dan masukkan perintah berikut.

PM> install-package FluentNHibernate

Setelah berhasil diinstal, Anda akan melihat pesan berikut.

Mari tambahkan kelas model sederhana dari Pelanggan dan program berikut menunjukkan implementasi kelas Pelanggan.

using System; 
using System.Collections.Generic; 
using System.Linq;
using System.Text; 
using System.Threading.Tasks;

namespace FluentNHibernateDemo { 
   class Customer { 
      public virtual int Id { get; set; } 
      public virtual string FirstName { get; set; } 
      public virtual string LastName { get; set; } 
   } 
}

Sekarang kita perlu membuat Pemetaan menggunakan NHibernate yang lancar, jadi tambahkan satu kelas lagi CustomerMapdalam proyek Anda. Berikut adalah implementasi kelas CustomerMap.

using FluentNHibernate.Mapping; 
using System; 
using System.Collections.Generic; 
using System.Linq; using System.Text; 
using System.Threading.Tasks;

namespace FluentNHibernateDemo { 
   class CustomerMap : ClassMap<Customer> { 
      public CustomerMap() { 
         Id(x => x.Id); 
         Map(x => x.FirstName); 
         Map(x => x.LastName); 
         Table("Customer"); 
      } 
   }
}

Mari tambahkan kelas lain NHibernateHelper di mana kami akan mengatur pengaturan konfigurasi yang berbeda.

using FluentNHibernate.Cfg; 
using FluentNHibernate.Cfg.Db; 
using NHibernate; 
using NHibernate.Tool.hbm2ddl;

namespace FluentNHibernateDemo { 

   public class NHibernateHelper { 
	
      private static ISessionFactory _sessionFactory;
		
      private static ISessionFactory SessionFactory { 
         get { 
            if (_sessionFactory == null)
            InitializeSessionFactory(); return _sessionFactory; 
         } 
      }
   
      private static void InitializeSessionFactory() { 
         _sessionFactory = Fluently.Configure() 
			
         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;
			
         .Database(MsSqlConfiguration.MsSql2008 .ConnectionString( 
            @"Data Source + Initial Catalog + Integrated Security + Connect Timeout
            + Encrypt + TrustServerCertificate + ApplicationIntent + 
            MultiSubnetFailover") .ShowSql() ) 
				
         .Mappings(m => m.FluentMappings
         .AddFromAssemblyOf<Program>()) 
         .ExposeConfiguration(cfg => new SchemaExport(cfg) 
         .Create(true, true)) 
         .BuildSessionFactory(); 
      }
		
      public static ISession OpenSession() { 
         return SessionFactory.OpenSession(); 
      } 
   }
}

Sekarang mari beralih ke Program.cs file di mana kita akan memulai sesi dan kemudian membuat pelanggan baru dan menyimpan pelanggan itu ke database seperti yang ditunjukkan di bawah ini.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks;

namespace FluentNHibernateDemo { 
   class Program { 
	
      static void Main(string[] args) { 
		
         using (var session = NHibernateHelper.OpenSession()) { 
			
            using (var transaction = session.BeginTransaction()) { 
               var customer = new Customer { 
                  FirstName = "Allan", 
                  LastName = "Bomer" 
               }; 
					
               session.Save(customer); 
               transaction.Commit();
               Console.WriteLine("Customer Created: " + customer.FirstName + "\t" +
                  customer.LastName); 
            } 
				
            Console.ReadKey(); 
         } 
      } 
   } 
}

Mari jalankan aplikasi Anda dan Anda akan melihat output berikut.

if exists (select * from dbo.sysobjects where id = object_id(N'Customer') and
   OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table Customer

create table Customer (
   Id INT IDENTITY NOT NULL,
   FirstName NVARCHAR(255) null,
   LastName NVARCHAR(255) null,
   primary key (Id)
)

NHibernate: INSERT INTO Customer (FirstName, LastName) VALUES (@p0, @p1); 
   select SCOPE_IDENTITY();@p0 = 'Allan' [Type: String (4000)], 
   @p1 = 'Bomer' [Type: String (4000)]
   Customer Created: Allan Bomer

Seperti yang Anda lihat, pelanggan baru dibuat. Untuk melihat catatan pelanggan, mari pergi ke database dan lihat Lihat Data dan Anda akan melihat bahwa 1 Pelanggan ditambahkan.