NHibernate - Hızlı Kılavuz

Bu bölümde, NHibernate'in ne olduğu, hangi tüm platformların uygulanabileceği, avantajları ve bununla ilgili diğer yönleri tartışacağız.

NHibernate nedir?

NHibernate, .NET çerçevesi için olgun, açık kaynaklı bir nesne ilişkisel eşleyicidir. Aktif olarak geliştirildi, tam özellikli ve binlerce başarılı projede kullanıldı. Üstüne inşa edilmiştirADO.NET ve mevcut sürüm NHibernate 4.0.4.

  • NHibernate, açık kaynaklı bir .NET nesne ilişkisel eşleştiricisidir ve GNU Lesser General Public License.

  • Popüler bir Java nesne ilişkisel eşleştiricisi olan Hibernate'e dayalıdır ve çok olgun ve aktif bir kod tabanına sahiptir.

  • Nesne yönelimli bir etki alanı modelini geleneksel bir ilişkisel veritabanına eşlemek için bir çerçeve sağlar.

  • NHibernate, Tom Barrett ve bu proje ilk taahhütleri olan Şubat 2003'ten beri var.

  • Bu büyük bir proje ve çok sayıda işlevsellik sağlıyor.

  • Var NuGet package kullanılabilir, bu da bir projeye eklemeyi çok kolaylaştırır.

Neden NHibernate?

Şimdi soru neden ihtiyacımız olduğu. object-relational mappers? Bunun nedeni, nesne dünyası ile ilişkisel dünya arasında bir kopukluk olmasıdır.

  • Nesne dünyasında her şey objects; Verilerimize sahip olan nesnelere dedik.

  • İlişkisel dünyanın tamamı küme tabanlıdır ve biz nesne dünyasından farklı tablolar ve satırlarla uğraşıyoruz.

  • Nesne dünyasında bizde unidirectional associations. Bir müşterinin bir siparişi gösteren bir işaretçisi varsa, bu, bir siparişin müşteriye geri dönen bir işaretçisinin olduğu anlamına gelmez, olabilir veya olmayabilir.

  • İlişkisel dünyada, tüm dernekler bidirectional ve bir yabancı anahtar ile yapılabilir.

  • Tüm dernekler doğası gereği çift yönlüdür, bu nedenle nesne-ilişkisel haritalama ile uğraşırken, bu kopukluğu da ele almamız gerekir.

  • Nesne dünyasında, tek yönlü işaretçilerle çalışıyoruz, oysa ilişkisel dünyada, doğası gereği çift yönlü olan yabancı anahtarlarımız var.

  • Nesne dünyası, bir aracın bir dizi farklı alt sınıfa sahip olabileceği bu miras kavramına sahiptir, yani bir araba bir tür araç, bir tekne bir tür araç ve bir spor araba bir tür araba, bu türler miras ilişkileri.

  • İlişkisel dünya bu miras kavramına sahip değil.

Haritalama

Peki tüm bunları nasıl haritalandıracağız disjoint relationships?Bu eşleme kavramı, nesne-ilişkisel eşleştiriciden gelir. Aşağıdaki şemada gösterildiği gibi anlaşılması gereken başlıca üç şey vardır.

  • Uygulamanızda, tipik olarak C # kodu olan sınıf tanımlarına ve Çalışan sınıfı, Müşteri sınıfı, Sipariş sınıfı gibi sınıflarımızı temsil eden .NET koduna ihtiyacınız olacak.

  • Altta, bizim olan bir veritabanı şemasını görebilirsiniz. Data Definition Language müşteri tablosunun neye benzediğini, çalışan tablosunun neye benzediğini belirten ilişkisel bir veritabanında.

  • Bunların arasında, nesne-ilişkisel eşleştiriciye satırlar ve sütunlar ve yabancı anahtar ilişkileri açısından C # 'daki nesne dünyasından veritabanı dünyasına nasıl tercüme edileceğini söyleyen eşleme meta verilerine sahibiz.

  • Bu eşleme meta verileri çeşitli farklı şekillerde temsil edilebilir ve NHibernate uygulamasında en tipik olan bu farklı yollardan birkaçına bakacağız.

  • Tarafından temsil edilmektedir HBM (Hibernate Mapping) XML dosyaları olan dosyalar.

Veritabanı Destekli

NHibernate, çok çeşitli farklı veritabanlarını destekler. Mevcut herhangi bir ilişkisel veri tabanına NHibernate'e erişilebilir.

  • SQL sunucusu, desteklenen birincil veritabanıdır, çoğu geliştiricinin geliştirme sırasında kullandığı şey, muhtemelen en yaygın olanıdır.

  • Aynı zamanda works very well with Oracle.

  • Ayrıca DB2, Firebird, MySQL, PostgreSQL, SQL Lite'ı da destekler

  • Ayrıca .... sahip ODBC and OLEDB drivers.

Günümüzde birçok sistem katmanlı mimariyle tasarlanıyor, NHibernate de buna sahip ve bu tasarımla mükemmel bir şekilde çalışıyor.

Katmanlı Mimari

Katmanlı bir mimari, bir sistemi birkaç gruba ayırır; burada her grup, belirli bir sorun alanını ele alan kodu içerir ve bu gruplara katman adı verilir. Kurumsal düzeydeki uygulamaların çoğu,high-level application architecture üç katmandan oluşan -

  • Sunum katmanı
  • İş katmanı
  • Kalıcılık katmanı

Örneğin, sunum katmanı olarak da bilinen bir kullanıcı arabirimi katmanı, web sayfaları oluşturmak ve kullanıcı girdisini işlemek için tüm uygulama kodunu içerebilir.

Katmanlama yaklaşımının en büyük faydalarından biri, diğer katmanlarda önemli bir kesinti olmadan genellikle bir katmanda değişiklik yapabilmeniz ve böylece sistemleri yapabilmenizdir. lesser fragile and more maintainable.

Sunum Katmanı

  • Kullanıcı Arayüzünü, sayfaları, diyalogları veya ekranları çizmekten ve kullanıcı girdisini toplamaktan ve gezinmeyi kontrol etmekten sorumlu kodu içeren en üst katmandır.

İş Katmanı

  • İş katmanı, kullanıcıların sorun alanının bir parçası olarak anlayacağı tüm iş kurallarını veya sistem gereksinimlerini uygulamaktan sorumludur.

  • Ayrıca kalıcılık katmanı tarafından tanımlanan modeli yeniden kullanır.

Kalıcılık Katmanı

  • Kalıcılık katmanı, uygulama verilerinin kaydedilmesinden ve alınmasından sorumlu olan sınıflardan ve bileşenlerden oluşur.

  • Bu katman ayrıca model sınıfı ile veritabanı arasında bir eşlemeyi tanımlar. NHibernate, öncelikle bu katmanda kullanılır.

Veri tabanı

  • Veritabanı, .NET uygulamasının dışında bulunmaktadır.
  • Sistem durumunun gerçek, kalıcı temsilidir.
  • Bir SQL veritabanı kullanılıyorsa, veritabanı ilişkisel şemayı ve muhtemelen depolanmış prosedürleri içerir.

Yardımcı / Yardımcı Sınıflar

  • Her uygulamanın, diğer katmanları destekleyen bir yardımcı veya yardımcı sınıflar kümesi vardır: örneğin, UI pencere öğeleri, mesajlaşma sınıfları, İstisna sınıfları ve günlük kaydı araçları.

  • Bu öğeler, katmanlı bir mimaride ara katman bağımlılığı kurallarına uymadıklarından katman olarak kabul edilmezler.

NHibernate Mimarlık

  • NHibernate uygulamasının üst düzey bir görünümüdür ve ayrıca basit NHibernate mimarisini de görebilirsiniz.

  • Uygulama kodu NHibernate kullanır ISession ve IQuery Kalıcılık işlemleri için API'ler ve yalnızca ideal olarak NHibernate kullanarak veritabanı işlemlerini yönetmek zorundadır ITransaction API.

NHibernate'i gerçekten kullanmaya başlayabilmemiz için, üzerine inşa edildiği temeli anlamamız gerekiyor. NHibernate, nesne ilişkisel haritalama veya ORM fikrine dayanan bir kalıcılık teknolojisidir.

ORM nedir?

Nesne-İlişkisel Haritalama (ORM) bir programming techniquenesne yönelimli programlama dillerinde uyumsuz tip sistemler arasında veri dönüştürmek için. Başka bir deyişle, bir uygulamanın iş nesnelerini ilişkisel veritabanı tablolarıyla eşleştirme kavramıdır, böylece verilere bir uygulamanın nesne modeli aracılığıyla kolayca erişilebilir ve tamamen güncellenebilir.

  • İlişkisel veritabanlarının verileri depolamak için iyi bir araç sağladığını bildiğiniz gibi, nesne yönelimli programlama ise karmaşık uygulamalar oluşturmak için iyi bir yaklaşımdır.

  • Genel olarak NHibernate ve ORM, önemsiz olmayan iş mantığı, etki alanı modeli ve bir çeşit veritabanı içeren uygulamalarla en çok ilgilidir.

  • ORM ile, nesneleri ilişkisel verilere kolayca dönüştürebilen ve tekrar geri alabilen bir çeviri katmanı oluşturmak çok kolaydır.

  • ORM kısaltması, nesne rol modellemesi anlamına da gelebilir ve bu terim, nesne / ilişkisel haritalama alakalı hale gelmeden önce icat edilmiştir.

  • Veritabanı modellemesinde kullanılan bilgi analizi için bir yöntemi açıklar.

Neden ORM?

ORM bir framework bu, nesne yönelimli dillerde bulunan nesnelerin dünyasını ilişkisel veritabanlarında bulunan ilişkisel tablolardaki satırlarla eşlemenizi sağlar

Bu kavramı anlamak için aşağıdaki diyagrama bir göz atalım.

  • Yukarıdaki diyagramda, sağ tarafta, bireysel bir çalışanla ilişkilendirilmiş her veri parçasını içeren sütunları içeren Çalışan adlı bir tablomuz olduğunu görebilirsiniz.

  • Her çalışanı benzersiz bir şekilde tanımlayan bir Kimlik için bir sütunumuz var.

  • Çalışanın adı için bir sütun, katılma tarihleri ​​için başka bir sütun ve son olarak çalışanın yaşını belirten bir sütun.

  • Yeni bir çalışanı masalarda saklamak için bir kod yazmak isteseydik, bu o kadar kolay değil.

  • Yukarıdaki diyagramda, Id, isim, katılım tarihi ve yaş için alanları olan bir çalışan nesnemiz olduğunu da görebilirsiniz.

  • ORM olmadan, bu nesneyi, çalışan verilerini çalışan tablosuna ekleyecek birkaç farklı SQL ifadesine çevirmeliyiz.

  • Dolayısıyla, yukarıdaki senaryoyu gerçekleştirmek için SQL'i oluşturmak için kod yazmak o kadar da zor değil, ancak biraz sıkıcı ve yanlış yapmak oldukça kolay.

  • NHibernate gibi bir ORM kullanarak, belirli sınıfların ilişkisel tablolarla nasıl eşleştirilmesi gerektiğini bildirebilir ve ORM veya NHibernate'in, çalışan tablomuzdaki sorgu verilerini eklemek, güncellemek, silmek için SQL oluşturmanın kötü işiyle uğraşmasına izin verebiliriz.

  • Bu, kodumuzu nesneleri kullanmaya odaklanmamızı ve bu nesnelerin otomatik olarak ilişkisel tablolara dönüştürülmesini sağlar.

  • Yani gerçekten bir ORM'nin yaptığı şey, bizi nesneleri manuel olarak tablolarla eşlemek zorunda kalmaktan kurtarmasıdır.

NHibernate üzerinde çalışmaya başlamak için Visual Studio ve NHibernate paketine ihtiyacımız olacak.

Visual Studio Kurulumu

Microsoft, bir free version Visual Studio'nun SQL Server ve şuradan indirilebilir: https://www.visualstudio.com Kurulum için adımlar aşağıdadır.

Step 1 - İndirme tamamlandıktan sonra yükleyiciyi çalıştırın, ardından aşağıdaki iletişim kutusu görüntülenecektir.

Step 2 - Kur düğmesine tıklayın ve kurulum işlemi başlayacaktır.

Step 3 - Kurulum işlemi başarıyla tamamlandığında, aşağıdaki iletişim kutusunu göreceksiniz.

Step 4 - Bu iletişim kutusunu kapatın ve gerekirse bilgisayarınızı yeniden başlatın.

Step 5- Şimdi, aşağıdaki iletişim kutusunu açacak olan Başlat Menüsünden Visual Studio'yu açın. İlk kez hazırlık için biraz zaman alacak.

Step 6 - Tüm bunlar yapıldıktan sonra, Visual Studio'nun ana penceresini göreceksiniz.

NHibernate Paket Kurulumu

NHibernate, .NET çerçevesi için olgun, açık kaynaklı bir nesne ilişkisel eşleyicidir. Aktif olarak geliştirilmiş, tam özellikli ve binlerce başarılı projede kullanılmaktadır. NHibernate paketini aşağıdaki yöntemlerle kurabilirsiniz.

Direkt indirme

  • Zip dosyasını dosyadan indirin https://sourceforge.net/ gerekli olan tüm ikili dosyaları içeren.

  • Bu zip dosyasını çıkarın ve tüm bu ikili dosyaları projenize dahil edin.

NuGet Kullanarak Yükleme

  • NHibernate'i kurmanın başka bir yolu, NHibernate'i bir projeye dahil etmenin en kolay yolu olan NHibernate paketini kurmak için NuGet'i kullanmaktır.

  • Tüm NHibernate bağımlılıklarını indirecek ve gerekli tüm derlemelere referanslar oluşturacak.

  • NHibernate'i kurmak için, Paket Yöneticisi Konsolunda aşağıdaki komutu çalıştırın.

install-package NHibernate

Artık başvurunuzu başlatmaya hazırsınız.

Bu bölümde, NHibernate kullanarak basit bir örneğe nasıl başlanacağına bakacağız. Biz inşa edeceğizsimple console application. Bir konsol uygulaması oluşturmak için, NHibernate paketini kullanarak uygulamanızı test etmek için ihtiyacınız olan tüm özellikleri içeren Visual Studio 2015'i kullanacağız.

Aşağıda, Visual Studio'da bulunan proje şablonlarını kullanarak bir proje oluşturma adımları verilmiştir.

Step 1 - Görsel stüdyoyu açın ve Dosya → Yeni → Proje menü seçeneğine tıklayın.

Step 2 - Yeni bir Proje iletişim kutusu açılır.

Step 3 - Sol bölmeden Şablonlar → Görsel C # → Pencereler'i seçin.

Step 4 - Orta bölmede Konsol Uygulaması'nı seçin.

Step 5 - Ad alanına proje adını 'NHibernateDemoApp' girin ve devam etmek için Tamam'ı tıklayın.

Step 6 - Proje Visual Studio tarafından oluşturulduktan sonra, Çözüm Gezgini penceresinde birkaç dosyanın görüntülendiğini göreceksiniz.

Basit bir konsol uygulama projesi oluşturduğumuzu bildiğiniz gibi, şimdi NHibernate paketini konsol projemize dahil etmemiz gerekiyor.

Araçlar menüsüne gidin ve NuGet Paket Yöneticisi → Paket Yöneticisi Konsolu'nu seçin, Paket Yöneticisi Konsolu penceresini açacaktır.

Yukarıda gösterilen komutu belirtin Package Manager Consolepenceresini açın ve enter tuşuna basın, tüm NHibernate bağımlılıklarını indirecek ve gerekli tüm derlemelere referanslar oluşturacaktır. Kurulum tamamlandığında, aşağıdaki resimde gösterildiği gibi mesajı göreceksiniz.

Artık NHibernate'i eklediğimize göre, uygulamaya başlayabiliriz. Öyleyse, çok basit bir haritayı çizerek başlayacağıztable aranan Student, ID adında bir tamsayı birincil anahtara ve FirstName ve LastName sütununa sahip olan.

Bu öğrenciyi temsil edecek bir sınıfa ihtiyacımız var, öyleyse çözüm gezgininde projeye sağ tıklayarak Öğrenci adında yeni bir sınıf oluşturalım ve ardından Yeni Öğe Ekle iletişim kutusunu açacak olan Ekle → Sınıf'ı seçelim.

Giriş Student.csad alanında, Ekle düğmesini tıklayın. Bu Öğrenci sınıfında, ID adında tam sayı birincil anahtarımıza sahip olmalıyız ve bu dizeyi oluşturmalıyız,FirstName ve LastName Öğrenci sınıfının aşağıdaki tam uygulamasında gösterildiği gibi alanlar.

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; } 
   } 
}

NHibernate uygulamasındaki modellerle uğraşırken, tüm alanlarınızı sanal yapmak en kolayıdır. Bu, kullanacağımız ve bunu arka uç veritabanına eşleyeceğimiz basit NHibernate modelimizdir.

Şimdi Program sınıfındaki Main metoduna gidelim ve yeni bir NHibernate konfigürasyon nesnesi oluşturalım.

Sağlamamız gereken ilk şey, connection string. Bu, veritabanına özgü bir bağlantı dizesidir ve bağlantı dizesini bulmanın en kolay yolu, veri tabanına sağ tıklamaktır.SQL Server Object Explorer ve Özellikler'i seçin.

Özellikler Penceresini açacak, şimdi aşağı kaydırın ve Özellikler penceresinde Bağlantı Dizesi alanını göreceksiniz.

Bağlantı dizesini kopyalayın ve kodunuzda belirtin. Aşağıda, NHibernate için yapılandırmaya ihtiyaç duyduğumuz Ana yöntemin uygulaması yer almaktadır.

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(); 
         } 
      } 
   } 
}

Bağlantı dizesinden sonra, bir sürücü sağlamamız gerekir. SQLClientDriver ve sonra ona bir diyalekt, SQL Server'ın hangi sürümünü sağlamamız gerekiyor ve MS SQL 2008 kullanacağız.

NHibernate artık veritabanına nasıl bağlanılacağını biliyor. Yapmamız gereken diğer şey, ona haritalayacağımız modellerin bir listesini sağlamaktır.

Bunu bir montaj ekleyerek yapabiliriz, yani Assembly.GetExecutingAssemblyve burası programın eşleme dosyalarını bulacağı yerdir. Eşleme dosyaları NHibernate'e C # sınıflarından veritabanı tablolarına nasıl geçileceğini söyler.

SessionFactory, NHibernate'i başlatmak için gerekli tüm meta verileri derler. SessionFactory, veritabanı bağlantılarına kabaca benzeyen oturumlar oluşturmak için kullanılabilir. Bu yüzden uygun yol, onu kullanım bloğunda kullanmaktır. söyleyebilirimvar session eşittir sessionFactory.OpenSession ve bunu işleminin içinde yapmak isteyeceğim.

Oturum açıldıktan sonra, oturuma yeni bir işlem başlatmasını söyleyebilir ve daha sonra burada biraz mantık gerçekleştirebiliriz. Bu nedenle, bazı veritabanı mantığı uygulayın ve sonunda bu işlemi gerçekleştirin.

Bu bölümde, bazılarını ele alacağız basic mappingve son bölümden, veritabanı tablosunun yanı sıra C # sınıf tanımına da sahip olduğumuzu biliyorsunuz. Şimdi, C # 'dan veritabanına ve tekrar geri nasıl tercüme edileceğini açıklayan bir eşlemeye ihtiyacımız var.

Öyleyse devam edelim ve çözüm gezgininde projeye sağ tıklayarak yeni bir XML dosyası ekleyelim ve Ekle → Yeni Öğe ...

Giriş Student.hbm.xmlisim alanında. Varsayılan bir derleme belirtmemiz gerekiyor.NHibernateDemoAppve ayrıca varsayılan bir ad alanı belirtin. Bu, bu dosyada yapacağımız diğer birçok tür tanımını kısaltır.

XML dosyasındaki uygulama aşağıdadır -

<?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>

Bir sınıf tanımlamamız gereken sonraki şey; bu sınıf bizim olacakStudent class. Sonra, NHibernate'e ID'nin ismini söylemeliyiz, ki bu ID ve ayrıca NHibernate'e ID'lerin nasıl üretileceğini söylemeliyim, böylece bizim jeneratörümüz native tipte olacak.

Yerel tür üreteci, SQL Server gibi bir veritabanında kimlik sütununu, kimlik türünü kullanacağı anlamına gelir.

Yapmamız gereken bir sonraki şey, mülklerin isimlerini vermektir. Bu nedenle, FirstName ve LastName için iki özellik daha ekleyin.

Şimdi, bu eşleme dosyalarını derlemeden okuyoruz. Dolayısıyla, bunu yapmanın tercih edilen yolu bunlara sahip olmaktır.HBM filesmontajınıza pişmiş. Bunu sadece bir özellik belirleyerek yapabiliriz.

Şimdi çözüm gezgininde projeye sağ tıklayın ve Özellikler'i seçin, göreceksiniz. Build Action field İçeriğin varsayılan olarak seçildiği.

Açılır listeden gömülü kaynağı seçin.

Yani bu aslında XML dosyasını NHibernateDemoApp montaj.

Bu bölümde temel konuları ele alacağız CRUD operations. Artık, öğrenci sınıfımızı başarıyla uyguladığımız için sistemimiz başlamaya hazır olduğuna göre, eşleme dosyalarını da tanımladık ve NHibernate'i yapılandırdık. Şimdi CRUD işlemlerini gerçekleştirmek için bazı sorgular kullanabiliriz.

Veri Oluşturun

Gördüğünüz gibi Öğrenci tablomuzda hiçbir verimiz yok NHibernateDemoDB veri tabanı.

Bu nedenle, biraz veri eklemek için, Add/Create aşağıda gösterildiği gibi işlem.

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(); 
}

Gördüğünüz gibi, iki öğrenci oluşturduk ve sonra da Save () yöntemini çağırdık. OpenSession ve sonra Commit () çağırın BeginTransaction. İşte tam uygulamaProgram.cs dosya

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(); 
         } 
      } 
   } 
}

Şimdi bu uygulamayı çalıştıralım ve ardından SQL Server Object Explorer'a gidip veritabanınızı yenileyelim. Yukarıdaki iki öğrencinin NHibernateDemoDB veritabanındaki Öğrenci tablosuna eklendiğini göreceksiniz.

Öğrenci Tablosundan Verileri Okuyun

Şimdi öğrenci tablomuzda iki kaydımızın olduğunu görebilirsiniz. Bu kayıtları tablodan okumak için,CreateCriteria() Aşağıdaki kodda gösterildiği gibi OpenSession.

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(); 
}

Dolayısıyla, kayıt listesini istiyorsanız, Öğrenci türü listesi diyebiliriz.

Şimdi kullanın foreach tüm öğrenciler aracılığıyla ve kimliği yazdır deyin, FirstMidName ve LastNamekonsolda. Şimdi bu uygulamayı tekrar çalıştıralım ve konsol penceresinde aşağıdaki çıktıyı göreceksiniz.

1 Allan Bommer
2 Jerry Lewis

Ayrıca herhangi bir kaydı ID'yi belirterek de alabilirsiniz. Get() Aşağıdaki kodu kullanarak OpenSession yöntemi.

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(); 
}

Şimdi uygulamanızı çalıştırdığınızda aşağıdaki çıktıyı göreceksiniz.

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

Kaydı Güncelle

Tablodaki kaydı güncellemek için, önce o belirli kaydı getirmemiz ve ardından bu kaydı, Update() Aşağıdaki kodda gösterildiği gibi OpenSession yöntemi.

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();
}

Şimdi uygulamanızı çalıştırdığınızda aşağıdaki çıktıyı göreceksiniz.

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

Gördüğünüz gibi, 1'e eşit LastName, Bommer'dan Donald'a güncellenmiştir.

Kaydı sil

Tablodan herhangi bir kaydı silmek için, önce o belirli kaydı getirmemiz ve ardından bu kaydı silmemiz gerekir. Delete() Aşağıdaki kodda gösterildiği gibi OpenSession yöntemi.

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(); 
}

Şimdi uygulamanızı çalıştırdığınızda aşağıdaki çıktıyı göreceksiniz.

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

Gördüğünüz gibi kimliği 1'e eşit olan kayıt artık veritabanında bulunmuyor. Veritabanını SQL Server Nesne Gezgini'nde de görebilirsiniz.

Bu bölümde, veritabanındaki tüm kayıtların nasıl olduğunu anlayacağız. retrieved, updated, created, and deleted ve bu sorgular tam olarak nasıl gerçekleştirilir?

Tüm bunları anlamak için, konfigürasyonumuza konsolda SQL'i günlüğe kaydeden bir seçenek ekleyebiliriz. İşte SQL sorgusunu günlüğe kaydedecek basit ifade -

x.LogSqlInConsole = true;

Şimdi, NHibernateDemoDB veritabanındaki öğrenci tablomuzda iki kaydımız var. Aşağıdaki kodda gösterildiği gibi tüm kayıtları veritabanından alalım.

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(); 
         } 
      } 
   } 
}

Öyleyse devam edelim ve bu uygulamayı tekrar çalıştıralım ve aşağıdaki çıktıyı göreceksiniz -

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

Gördüğünüz gibi select clauseVeritabanına gönderildiğinde, aslında ID, FirstMidName ve LastName'i alacak olan tümce gibidir. Yani tüm bunlar, çok sayıda kaydın sunucunuza geri getirilmesi ve sunucu tarafında işlenmesi yerine veritabanına gönderiliyor ve orada işleniyor.

NHibernate Profiler

Bu sonuçlara bakmanın başka bir yolu da NHibernate Profiler'ı kullanmaktır. NHibernate Profiler ticari bir araçtır, ancak NHibernate uygulamalarıyla çalışmak için çok kullanışlıdır. NHibernate Profiler'ı NuGet'ten uygulamanıza kolayca yükleyebilirsiniz.

NuGet Paket Yöneticisi → Paket Yöneticisi Konsolu'nu seçerek Araçlar menüsünden NuGet Manager konsoluna gidelim. Paket Yöneticisi Konsolu penceresini açacaktır. Aşağıdaki komutu girin ve enter tuşuna basın.

PM> install-package NHibernateProfiler

NHibernate Profiler için gerekli tüm ikili dosyaları kuracaktır, başarıyla kurulduktan sonra aşağıdaki mesajı göreceksiniz.

NHibernate Profiler'ın kurulduktan sonra başlatıldığını da göreceksiniz. Kullanmak için lisans gerektirecektir, ancak demo amacıyla NHibernate Profiler'ın 30 günlük deneme sürümünü kullanabiliriz.

NHibernate Profiler artık web uygulamalarıyla çalışmak üzere optimize edilmiştir ve eklediklerini göreceksiniz. App_Start folderçözüm gezgininde. Tüm bunları basit tutmak için, App_Start klasörünü silin ve ayrıca Program sınıfında Main metodunun başlangıcına bir ifadenin eklendiğini göreceksiniz.

App_Start.NHibernateProfilerBootstrapper.PreStart();

Bu ifadeyi de kaldırın ve sadece basit bir çağrı ekleyin NHibernateProfiler.Initialize aşağıdaki kodda gösterildiği gibi.

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(); 
         } 
      } 
   
   }
}

Şimdi uygulamayı çalıştırdığınızda, verileri NHibernate Profiler uygulamasına gönderecek.

Burada görüyorsunuz, işlemi başlattığımızı, SQL'in veritabanına ne yaptığını güzel bir biçimde gösteren güzel bir ekranımız var.

Dolayısıyla bu, NHibernate uygulamanızın içinde tam olarak ne olduğunu belirlemek için çok yararlıdır. Uygulama, daha çok bir SQL Profiler gibi bir şeye ihtiyaç duyduğunuzda, ancak NHibernate bilgisiyle, belirli bir karmaşıklık düzeyine ulaştığında inanılmaz derecede yararlı hale gelir.

Bu bölümde ekleyeceğiz IntelliSense NHibernate eşleme dosyalarımıza (*.hbm.xml files). Öğrenci sınıfını eşlerken gözlemlediğiniz gibi, şu anda kullanılabilir IntelliSense'e sahip değiliz. Sahip olmak çok yararlıXML schemasmevcut. Dolayısıyla bu bölümde, bu NHibernate XML dosyaları için Visual Studio'da IntelliSense'in nasıl ekleneceğini anlayacaksınız.

Eşleme dosyasını açın ve ana menüde XML menü seçeneğinin göründüğünü göreceksiniz.

XML → Şemalar… menü seçeneğini seçin ve XML Şemaları iletişim kutusunu görüntüleyecektir.

Dosya iletişim kutusunu açan iletişim kutusunun sağ üst kısmında bulunan Ekle… düğmesini seçin. Şimdi gidinpackages folderProjenizin Çözüm klasöründe bulunan ve projenize dahil edilen farklı paketleri göreceksiniz.

Şimdi, çift tıklayın NHibernate.4.*** folder ve NHibernate yapılandırmasını ve eşlemesini tanımlayan iki şema (* .xsd) dosyasını veya XML şema tanımlama dosyalarını göreceksiniz.

Bu iki şema dosyasını seçin ve Aç düğmesine tıklayın.

NHibernate şemalarının XML Şemaları iletişim kutusuna eklendiğini görebilirsiniz. Tamam düğmesini tıklayın. Şimdi, yeni bir özellik etiketi başlatalım ve burada tam IntelliSense'e sahip olduğumuzu göreceksiniz.

Nesne-ilişkisel eşleştirme sırasında çok fazla zaman kazandıran IntelliSense artık sizin için kullanılabilir.

Bu bölümde, haritalama veri türlerini ele alacağız. Varlıkları eşlemek basittir, varlık sınıfları her zaman veritabanı tablolarıyla eşlenir.<class>, <subclass>, and <joined-subclass>eşleme öğeleri. Değer türleri daha fazlasına ihtiyaç duyar, bu da eşleme türlerinin gerekli olduğu yerdir.

NHibernate, çok çeşitli veri türlerini eşleyebilir. Desteklenen en yaygın veri türlerinin listesi aşağıdadır.

Eşleme türü .NET türü System.Data.DbType
Int16 System.Int16 DbType.Int16
Int32 System.Int32 DbType.Int32
Int64 System.Int64 DbType.Int64
Tek System.Single DbType.Single
Çift System.Double DbType.Double
Ondalık System.Decimal DbType.Decimal
Dize System.String DbType.String
AnsiString System.String DbType.AnsiString
Bayt System.Byte DbType.Byte
Char System.Char DbType.StringFixedLength — bir karakter
AnsiChar System.Char DbType.AnsiStringFixedLength — bir karakter
Boole System.Boolean DbType.Boolean
Kılavuz System.Guid DbType.Guid
PersistentEnum System.Enum (bir numaralandırma) Temel değer için DbType
Doğru yanlış System.Boolean DbType.AnsiStringFixedLength - 'T' veya 'F'
Evet Hayır System.Boolean DbType.AnsiStringFixedLength - 'Y' veya 'N'
DateTime DateTime DbType.DateTime — milisaniyeleri dikkate almaz
Keneler System.DateTime DbType.Int64
Zaman aralığı System.TimeSpan DbType.Int64
Zaman damgası System.DateTime DbType.DateTime - veritabanının desteklediği kadar spesifik
İkili System.Byte [] DbType.Binary
BinaryBlob System.Byte [] DbType.Binary
StringClob System.String DbType.String
Serileştirilebilir SerializableAttribute ile işaretlenmiş herhangi bir System.Object DbType.Binary
CultureInfo System.Globalization.CultureInfo DbType.String — kültür için beş karakter
Tür Sistem tipi Derleme Nitelikli Adını tutan DbType.String

Yukarıda verilen tablo, aşağıda belirtilen noktaları ayrıntılı olarak açıklamaktadır.

  • Basit sayısal türlerden, çeşitli şekillerde eşlenebilen dizelere kadar her şey varchars, chars vb. yanı sıra dize blobları ve veritabanlarının desteklediği tüm türler.

  • Ayrıca harita yapabiliyor Booleans, hem sıfırlar hem de birler kullanan alanlara, doğru, yanlış veya T ve F içeren karakter alanlarına.

  • Veritabanındaki arka uç, boole değerleriyle nasıl eşleştiğini tanımlamanın çok çeşitli yolları vardır.

  • Haritalandırmayı halledebiliriz DateTimesaat dilimi uzaklıkları, gün ışığından yararlanma saati vb. dahil ve hariç

  • Ayrıca haritalayabiliriz enumerations; bunları dizelerle veya onların temelindeki sayısal değerlerle eşleyebiliriz.

Hem veritabanında hem de Öğrenci sınıfında aynı özellik adlarına sahip olduğumuz basit bir örneğe bakalım.

Şimdi öğrenci sınıfında FirstMidName'i FirstName olarak değiştirelim, burada FirstMidName sütununu değiştirmeyeceğiz, ancak NHibernate'e bu dönüşümü gerçekleştireceğini nasıl söyleyeceğimizi göreceğiz. Güncellenen öğrenci sınıfı aşağıdadır.

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; } 
   }
}

NHibernate eşleme dosyasının uygulaması burada.

<?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>

Bu örnekte, FirstName alanının bir .NET dizesi ve FirstMidName sütununun bir SQL nvarchar. Şimdi NHibernate'e bu dönüşümü nasıl gerçekleştireceğini söylemek için adı şuna eşit ayarlayın:FirstName ve sütun eşittir FirstMidName ve bu özel dönüştürme için uygun olan eşleme türünü Dize'ye eşit olarak belirtin.

Aşağıdaki bir Program.cs dosya uygulaması.

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(); 
         } 
      } 
   }
}

Şimdi uygulamanızı çalıştırdığınızda aşağıdaki çıktıyı göreceksiniz.

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

Gördüğünüz gibi, farklı özellik adını veritabanındaki sütun adıyla eşlemiş.

Öğrenci sınıfına başka bir özellik ekleyeceğimiz başka bir örneğe bakalım. enumyazın. İşte Öğrenci sınıfı uygulaması.

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 
   } 
}

Gördüğünüz gibi, numaralandırmanın sahip olabileceği, Mükemmel, İyi, Orta, Zayıf ve Korkunç gibi çeşitli farklı değerleri vardır.

Eşleme dosyasına atladığınızda, bu özelliklerin her birinin yeni eklenenler de dahil olmak üzere eşleme dosyasında listelendiğini görebilirsiniz. AcademicStanding Emlak.

<?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>

Şimdi ayrıca veritabanını da değiştirmemiz gerekiyor, bu yüzden SQL Server Object Explorer'a gidin ve veritabanına sağ tıklayın ve Yeni Sorgu… seçeneğini seçin.

Sorgu düzenleyicisini açacak ve ardından aşağıdaki sorguyu belirleyecektir.

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) 
);

Bu sorgu önce mevcut öğrenci tablosunu kaldıracak ve ardından yeni bir tablo oluşturacaktır.

Yukarıda gösterildiği gibi Yürüt simgesine Clcik. Sorgu başarılı bir şekilde yürütüldüğünde bir mesaj görürsünüz.

Veritabanı ve Tablo açılır menüsünü genişletin ve ardından Öğrenci tablosuna sağ tıklayın ve Tasarımcıyı Görüntüle'yi seçin.

Şimdi, yeni oluşturulmuş ve AcademicStanding özelliğine sahip olan tabloyu göreceksiniz.

Aşağıda gösterildiği gibi iki kayıt ekleyelim Program.cs dosya.

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(); 
         } 
      } 
   } 
}

Şimdi uygulamanızı çalıştıralım ve konsol pencerenizde aşağıdaki çıktıyı göreceksiniz.

Fetch the complete list again

1 Allan Bommer Excellent
2 Jerry Lewis Good

Şimdi Öğrenci Tablosu'na sağ tıklayarak veri tabanına bakalım.

Verileri Görüntüle'yi seçin ve aşağıdaki ekran görüntüsünde gösterildiği gibi öğrenci tablosunda iki kaydı göreceksiniz.

İki kaydın eklendiğini ve Allan'ın AcademicStanding 0'a ve Jerry'nin AcademicStanding 1'e sahip olduğunu görebilirsiniz. Bunun nedeni, .Net'te varsayılan olarak ilk numaralandırma değerinin 0'a sahip olmasıdır; StudentAcademicStanding. Oysa Student.cs dosyasında İyi ikinci dosyadır, dolayısıyla değeri 1'dir.

Bu bölümde NHibernate yapılandırmasına bakacağız. NHibernate'i yapılandırmak için farklı yollarımız var. İki ana gruba ayrılır

  • XML tabanlı konfigürasyon
  • Kod tabanlı konfigürasyon

Kod Tabanlı Yapılandırma

Kod tabanlı konfigürasyon NHibernate'de yerleşiktir. NHibernate 3 çevresinde tanıtıldı ve şimdiye kadar kod tabanı yapılandırmasını kullandık.

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());

Tüm konfigürasyonlar C # kodunda belirtilmiştir. Burada yeni konfigürasyon nesnemize sahip olduğumuzu ve sonra kullandığımızı görebilirsiniz.loquacious configurationbu, veritabanını yapılandırmak için NHibernate 3.1 ile tanıtıldı. Hangi bağlantı dizesini kullanıyoruz, hangi veritabanına bağlanıyoruz ve kullanılacak lehçe. Ayrıca haritalama tertibatımızı doğrudan buraya ekliyoruz.

XML Tabanlı Yapılandırma

XML tabanlı yapılandırma kullanıyorsanız, bir hibernate.cfg.xml NHibernate şemasını kullanan bağımsız bir xml dosyası olan dosya veya bu NHibernate özel yapılandırmasını uygulamanızın içine yerleştirebilir veya web.cfg. Hibernate.cfg.xml adı varsayılan olarak, ancak bu xml dosyası için rastgele bir ad da kullanabiliriz.

NHibernateDemoApp projesine yeni bir xml dosyası ekleyerek ve buna hibernate.cfg.xml diyerek XML tabanlı yapılandırmaya bir göz atalım.

Hibernate.cfg.xml dosyasına aşağıdaki bilgileri girin.

<?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>

Yukarıdaki xml dosyasında görebileceğiniz gibi, C # 'da bahsedilen aynı konfigürasyonu belirledik.

Şimdi bu yapılandırmayı Program.cs dosyasından yorumlayalım ve Configure() yöntemi yükleyecek hibernate.cfg.xml dosya aşağıda gösterildiği gibi.

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(); 
         } 
      } 
   } 
}

Uygulamanızı tekrar çalıştıralım ve aynı çıktıyı göreceksiniz.

Fetch the complete list again

1 Allan Bommer Excellent
2 Jerry Lewis Good

Bu bölümde, NHibernate yapılandırmasının nasıl geçersiz kılınacağını ele alacağız. Aklınızda tutmanız gereken birkaç şey var.

  • Her şeyden önce, NHibernate'deki konfigürasyon katkı maddesidir.

  • Yani sadece tek bir xml dosyası kullanmak zorunda değilsiniz veya sadece kod tabanlı yapılandırmayı veya akıcı NHibernate kullanmak zorunda değilsiniz.

  • Uygulamanızı nasıl yapılandırmak istediğinize bağlı olarak tüm bu yöntemleri karıştırıp eşleştirebilirsiniz.

  • Unutulmaması gereken önemli nokta, son olarak konfigürasyonun kazanacağıdır.

Aşağıdaki örnekte, yapılandırma nesnemizi oluşturduğumuzu, onu kod tabanlı yapılandırmayı kullanarak yapılandırdığımızı ve son olarak cfg.configure() hibernate.cfg.xml dosyasını yükleyen yöntem.

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();
  • Dolayısıyla, bir hibernate.cfg.xml içindeki herhangi bir şey, kod tabanlı konfigürasyon tarafından belirlenen ayarları geçersiz kılar.

  • Bu iki işlemi tersine çevirerek, varsayılanları hibernate.cfg.xml içinde alabilir ve ardından kod tabanlı bir yapılandırma içinde geçersiz kılmalarımızı yapabiliriz.

  • Kod tabanlı yapılandırma kullanıyorsanız dışlayan hiçbir şey yoktur ve ayrıca hibernate.cfg.xml dosyasını kullanmanızı engelleyen hiçbir şey yoktur.

Yapılandırmayı xml tabanlı ve kod tabanlı yapılandırma karışımını kullanarak geçersiz kılacağımız basit bir örneğe bakalım.

Bağlantı dizesini de app.config aşağıdaki kodu kullanarak dosya.

<?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>

Bağlantı dizesi bazılarında oturuyor app.configvarsayılan bir ada sahip dosya. Şimdi, hibernate.cfg.xml dosyasında bağlantı dizesi yerine varsayılan adı belirtmemiz gerekiyor.

<?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>

Kod tabanlı yapılandırmanın bağlantı dizesi kısmı, sürücüsü ve lehçe kısmı hakkında yorum yapalım, çünkü program onu ​​hibernate.cfg.xml dosyasından ve LogSqlInConsole bölümü kod tabanlı yapılandırmada kalacaktır.

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(); 
         } 
      } 
   } 
}

Şimdi uygulamayı çalıştırdığınızda, programın günlüğü kod tabanlı yapılandırmadan ve diğer yapılandırmadan hibernate.cfg.xml dosyasından okuduğunu göreceksiniz.

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

Şimdi yapılandırmamızın bir kısmına sahibiz. hibernate.cfg.xml dosyasında, bazıları kod tabanlı yapılandırmanın içindedir ve kod tabanlı çağrıya karşı kod tabanlı arama sırasına bağlıdır. configure(), hangisinin diğerini geçersiz kıldığını değiştirebiliriz.

Bu bölümde, parti boyutu güncellemesini ele alacağız. Toplu iş boyutu şunları yapmanızı sağlar:control the number of updates desteklenen veritabanları için veritabanınıza tek bir gidiş-dönüş yolculuğuyla gider.

  • Güncelleme toplu boyutu NHibernate 3.2'den itibaren varsayılan olarak ayarlanmıştır.

  • Ancak daha eski bir sürüm kullanıyorsanız veya NHibernate uygulamanızı ayarlamanız gerekiyorsa, NHibernate'in performansını ayarlamak için kullanılabilecek çok yararlı bir parametre olan güncelleme toplu iş boyutuna bakmalısınız.

  • Aslında parti boyutu, bir grupta bir veritabanına kaç ek gönderileceğini kontrol eder.

  • Şu anda yalnızca SQL Server ve Oracle bu seçeneği desteklemektedir çünkü temeldeki veritabanı sağlayıcısının sorgu gruplamayı desteklemesi gerekir.

Toplu iş boyutunu, bir sete 10 kayıt ekleyecek 10 olarak ayarladığımız basit bir örneğe bakalım.

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

});

Veritabanına 25 kaydın ekleneceği tam uygulama.

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(); 
         } 
      }
   } 
}

Şimdi uygulamanızı çalıştıralım ve tüm bu güncellemelerin NHibernate profil oluşturucusuna atladığını görelim. Veritabanına 25 eklemek için 26 bireysel gidiş-dönüş gezimiz ve öğrenci listesinin alınması için bir tane var.

Şimdi, bu neden? Nedeni, NHibernate'in birselect scope identity Aşağıdaki kodda gösterildiği gibi kimlik için eşleme dosyasında yerel tanımlayıcı oluşturma stratejisini kullandığımızdan.

<?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>

Bu nedenle, aşağıdaki gibi farklı bir yöntem kullanmamız gerekir: guid.combyöntem. Guid.comb'ye gideceksek, müşterimize gitmeli ve bunu birguid. Böylece bu iyi çalışacak. Şimdi aşağıdaki kodu kullanarak yerelden guid.comb'ye geçelim.

<?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>

Yani bu kimlikleri oluşturmaktan sorumlu olan veritabanıdır. NHibernate'in hangi kimliğin üretildiğini öğrenmesinin tek yolu, hemen ardından onu seçmekti. Ya da bir öğrenci grubu oluşturmuşsak, oluşturulan öğrencinin kimliğiyle eşleşemez.

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 
   }
}

Sadece veritabanımızı güncellememiz gerekiyor. Öğrenci tablosunu bırakalım ve aşağıdaki sorguyu belirterek yeni bir tablo oluşturalım, bu yüzden SQL Server Nesne Gezgini'ne gidin ve veritabanına sağ tıklayın veNew Query… Seçenek.

Sorgu düzenleyicisini açar ve ardından aşağıdaki sorguyu belirtir.

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) 
);

Bu sorgu önce mevcut öğrenci tablosunu kaldıracak ve ardından yeni bir tablo oluşturacaktır. Gördüğünüz gibi kullandıkUNIQUEIDENTIFIER Kimlik olarak bir tamsayı birincil anahtarı kullanmak yerine.

Bu sorguyu yürütün ve ardından Designer view ve şimdi kimliğin aşağıdaki görüntüde gösterildiği gibi benzersiz bir tanımlayıcıyla oluşturulduğunu göreceksiniz.

Şimdi verileri eklerken program.cs dosyasından ID'yi kaldırmamız gerekiyor, çünkü şimdi guids bunun için otomatik olarak.

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(); 
         } 
      } 
   } 
}

Şimdi uygulamayı tekrar çalıştırın ve NHibernate profil oluşturucusuna bir göz atın. Şimdi NHibernate profil oluşturucusu 26 gidiş-dönüş yolculuk yapmak yerine sadece dört tane yapacak.

Tabloya on satır, ardından on satır ve daha sonra kalan beş satır eklenir. Ve kaydettikten sonra, tüm kayıtları almak için bir tane daha ekledi.

  • Bu yüzden elinden geldiğince onu onlu gruplara ayırır.

  • Dolayısıyla, çok sayıda kesici uç yapıyorsanız, bu, uygulamanızda uç performansını önemli ölçüde artırabilir, çünkü bunları yığınlayabilirsiniz.

  • Bunun nedeni, NHibernate'in bu kılavuzları kullanarak kendisini atamasıdır. guid.comb algoritması vardır ve bunu yapmak için veritabanına güvenmek zorunda değildir.

  • Bu yüzden parti boyutunu kullanmak, onu ayarlamak için harika bir yoldur.

Bu bölümde, cachingNHibernate uygulamalarında çalışır. Önbelleğe alma için yerleşik desteğe sahiptir. Basit bir özellik olarak görünse de gerçekte en karmaşık özelliklerden biridir. Birinci Seviye Önbellek ile başlayacağız.

Birinci Seviye Önbellek

Bu önbellek mekanizması, NHibernate'de varsayılan olarak etkindir ve önbellekle çalışmak için hiçbir şey yapmamıza gerek yoktur. Bunu anlamak için, veritabanımızda iki kaydımızın olduğunu görebileceğiniz gibi, basit bir örneğe bakalım.

Şimdi bu örnekte, kimliği 1 olan öğrenciyi alacağız ve aynı oturum sorgusunu aşağıdaki kodda gösterildiği gibi iki kez kullanacağız.

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(); 
         } 
      } 
   } 
}

Şimdi bu uygulamayı çalıştıralım ve sonucu NHibernate Profiler'da görelim.

NHibernate'in yalnızca bir sorgu başlattığını görünce şaşıracaksınız. NHibernate birinci seviye önbelleği bu şekilde kullanır. İlk sorgu yürütüldüğünde NHibernate, ID = 1 olan Öğrenciyi ilk seviye önbelleğinde önbelleğe aldı.

Dolayısıyla, ikinci sorgu yürütüldüğünde, NHibernate ilk önce ID = 1 olan birinci seviye önbellek Öğrenci varlığını arar, eğer o varlığı bulursa, NHibernate bunu bilir, aynı çalışan nesnesini tekrar almak için başka bir sorguyu ateşlemeye gerek yoktur. .

Bu bölümde, haritalama bileşenlerinden bahsedeceğiz. NHibernate'de,component is a value object. Kendine ait bir kimliği yoktur.

  • Bunun bir örneği bir para nesnesi olabilir, bir cüzdan veya bir cüzdan içinde para olabilir, ancak bu paranın tam kimliği önemsizdir.

  • Kendi birincil anahtarı yoktur, ancak bileşenlerin kendileri, sahip olan nesneyle aynı tabloda kalıcıdır.

Basit bir örneğe bakalım, bir öğrencinin adresi olan, bu da bir nesne Location class ile ilişkili.

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 
   } 
}

Şimdi, aşağıdaki sorguyu çalıştırarak veritabanını da güncellememiz gerekiyor, bu önce Öğrenci tablosunu bırakacak ve ardından Location sınıfı için bir sütun da içerecek yeni bir tablo oluşturacak.

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) 

);

Şimdi doğrudan Student sınıfının bir parçası olmayan, ancak bunlar Location sınıfının özellikleridir ve Location sınıf nesnesi öğrenci sınıfında tanımlanır. Doğru haritalamak için bir bileşene ihtiyacımız var. Bir bileşen oluşturalımstudent.hbm.xml dosya aşağıdaki kodda gösterildiği gibi.

<?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>

Bu bileşen Adrestir ve üzerinde bu farklı özelliklere sahiptir. Bu bilgilerle, NHibernate artık bunu haritalayabilecek kadar yeterli.

Şimdi burada, yeni bir öğrenci nesnesinin oluşturulup başlatıldığı ve ardından veritabanına kaydedildiği Program.cs dosyası var. Daha sonra listeyi veritabanından alacaktır.

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(); 
         } 
      }
   } 
}

Şimdi bu uygulamayı çalıştırabiliriz ve NHibernate bu değerleri veri tabanına kaydedebilir. Uygulamayı çalıştırdığınızda aşağıdaki çıktıyı göreceksiniz.

Fetch the complete list again

2 Allan Bommer Poor 123 Street Lahore Punjab Pakistan

İşte veri tabanındaki değerler.

Bileşenler, bir veritabanı tablosundaki sütunları kendi ayrı sınıflarına ayırmamızı sağlar.

  • Burada dikkat edilmesi gereken diğer husus ise Konumun bir sınıf olması, bir varlık olmamasıdır.

  • Değer türü bir nesnedir ve kendi birincil anahtarı yoktur.

  • İçerdiği Öğrenci ile aynı tabloya kaydedilir.

  • Bu nedenle burada bileşeni kullanıyoruz.

  • Bu, sınıf katmanımızı, sınıflarımızın nasıl tanımlandığına karşı veritabanımızın nasıl düzenlendiğini değiştirmek için büyük bir esneklik sağlar.

Bu bölümde NHibernate'deki ilişkilere bakacağız. NHibernate'deki ilişkileri nasıl anlayabileceğimize dikkatimizi çevirelim. En kolay yol, ilişkileri veritabanı perspektifinden düşünmektir.

  • Önce müşteri ve sipariş varlıkları arasında bazı ilişkiler kuracağımız yeni bir uygulama oluşturacağız.

  • Bakacağımız ilk ilişki, klasik bir koleksiyon ilişkisi.

  • Sipariş koleksiyonu olan bir müşterimiz var.

  • Bu bire çok bir ilişkidir ve veri tabanında 2 tablo ile temsil edilir ve sipariş tablosunda bir müşteri kimliği vardır ve müşteriye geri yabancı anahtar ilişkimiz vardır.

Öncelikle bir veritabanı ve Müşteri ve Sipariş tablosu oluşturmamız gerekiyor. Bunu SQL Server Explorer'da aşağıdaki sorguyu belirterek oluşturabilirsiniz.

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

Veritabanında iki tablo oluşturacaktır. Aşağıdaki resim Müşteri Tablosunu göstermektedir.

Aşağıdaki görüntü, müşteriyle olan yabancı anahtar ilişkisini görebileceğiniz Sipariş Tablosunu göstermektedir.

Bağlantı dizesini tanımlamamız gerekir. app.config dosyası, app.config dosyasının uygulamasıdır.

<?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>

NHibernate'i uygulamanıza yüklemek için NuGet Manager Console penceresinde aşağıdaki komutu çalıştırın.

install-package NHibernate

NHibernate yapılandırmasını yapılandırmak için yapılandırmayı şurada tanımlamamız gerekir: hibernate.cfg.xml dosya aşağıdaki kodda gösterildiği gibi.

<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>

Bu örnekte, Müşteri ve Sipariş olmak üzere iki alan sınıfı üzerinde çalışacağız.

Burada, iki sınıfa sahip olduğumuz Customer.cs dosya uygulaması, biri Customer sınıfı, diğeri ise nesnenin Customer sınıfında bir adres olarak kullanıldığı Location sınıfıdır.

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 
   } 
}

İşte eşleme dosyası Customer.hbm.xml Müşteri sınıfının Müşteri tablosuyla eşlendiği.

<?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>

Ayrıca bir Sipariş Sınıfımız var ve işte uygulaması Order.cs dosya.

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); 
      } 
   } 
}

Bire Bir İlişki

Ayrıca, Order sınıfını veritabanındaki Order tablosuna eşlemeliyiz, bu yüzden burada Order.hbm.xml dosya.

<?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>

Bire Çoğa İlişki

Burada, müşteri ve siparişler arasındaki bire çok ilişkisine bir göz atacağız. Burada müşterimiz var, yeni bir tane oluşturuyoruz ve koleksiyonun aşağıdaki sipariş çifti ile başlatıldığını görebilirsiniz.

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; 
}

Bu yüzden yeni bir müşteri oluşturacağız ve sonra kaydedeceğiz, kaydettikten sonra ID'yi bulacağız ve aşağıdaki programda gösterildiği gibi Ana yöntemde başka bir oturumda yeniden yükleyeceğiz.

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(); 
}

İşte eksiksiz Program.cs dosya uygulaması.

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; 
      } 
   } 
}

Bu uygulamayı çalıştırdığınızda aşağıdaki çıktıyı göreceksiniz.

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...

Gördüğünüz gibi başlangıçta müşterinin 2 siparişi var ama yeniden yüklediğimizde görülecek bir sipariş yok. Bakarsancustomer.hbm.xmldosya, burada gerçek sipariş koleksiyonunu eşleştirmediğimizi görebilirsiniz. Yani NHibernate bunun hakkında hiçbir şey bilmiyor. Devam edelim ve ekleyelim.

<?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>

Bu bir settir ve bu koleksiyonun adı, sipariş adı verilen bir tabloda saklanan 'Siparişler'dir. Yabancı anahtarın adı olan bir anahtar belirtmemiz veya siparişleri bulmamız gerekir. Bu siparişler, müşteri kimliği aracılığıyla tanımlanır veya bir müşteriye aittir. Ve sonra bunun bire çok bir ilişki olduğunu ve sipariş sınıfıyla olduğunu not etmeliyim.

Yeni müşteri siparişlerini aşağıdaki programda gösterildiği gibi veri tabanına kaydederek Ana yöntemi de biraz değiştirmemiz gerekiyor.

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();
}

Hangi müşterinin o ürünü sipariş ettiğini de belirledik. Bu nedenle, bu siparişi o müşteriyle ilişkilendirmek için çoka bir ilişki oluşturmamız gerekiyor.

Öyleyse hadi girelim Order.hbm.xml dosyasını açın ve çoktan bire ekleyin ve ardından müşteri alanını ve sütunu müşteri kimliğiyle adlandırın.

<?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>

Bu uygulamayı tekrar çalıştıralım ve şimdi aşağıdaki çıktıyı göreceksiniz.

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...

Bu bölümde, koleksiyonların nasıl temsil edileceğini ele alacağız. NHibernate içinde kullanabileceğimiz farklı koleksiyon türleri vardır, örneğin:

  • Lists
  • Sets
  • Bags

Şimdi, .NET perspektifinden, genellikle listelerle ilgileniyoruz veya çok basit veri yapılarını, listeleri, sözlükleri seviyoruz. .NET çok çeşitli farklı koleksiyon türlerine sahip değildir. Öyleyse NHibernate'in tüm bu farklı tiplere neden ihtiyacı var? Gerçekten veritabanına geri dönüyor.

Liste

  • Liste, benzersiz olması gerekmeyen sıralı öğeler koleksiyonudur.

  • Bunu kullanarak haritalayabiliriz IList <T>.

  • Dolayısıyla, geleneksel olarak bir adres listesine sahip olsak ve uygulama açısından öğelerin benzersiz olduğunu bilsek de, listedeki hiçbir şey bu listeye yinelenen öğeler eklememizi engellemiyor.

Ayarlamak

  • Küme, benzersiz öğelerden oluşan sırasız bir koleksiyondur. Bir kümeye 2 yinelenen öğe eklemeye çalışırsanız, bir istisna atar.

  • NHibernate'de bununla ilgili özel bir şey yok.

  • Bu, genel bir küme uygulamasına sahip olmanın uygun bir yoludur. .NET 4'teyseniz, yeniHashSet <T> bunları temsil etmek için, ancak çoğu NHibernate uygulamasında, bunun bir ISet olduğunu temsil ediyoruz.

  • Sırasızdır, eğer bir veri tabanından veya bir emir listesinden bir adres listesini geri alırsanız, maddeye göre belirli bir Sıraya koymadıkça hangi sırayla geldiklerini bilemezsiniz.

  • Yani genel olarak, bir veritabanından geri çektiğiniz veriler kümelerdir.

  • Sıralanmamış benzersiz öğe koleksiyonlarıdır.

Sırt çantası

  • Veritabanı dünyasında göreceğimiz bir diğer yaygın koleksiyon, yinelenen elemanlara sahip olabilmesi dışında tıpkı bir set gibi olan bir çantadır.

  • .NET dünyasında, bunu bir IList tarafından temsil ediyoruz.

Setler muhtemelen en yaygın olanıdır, ancak uygulamanıza bağlı olarak listeleri ve çantaları da göreceksiniz. Aşağıya bir göz atalımcustomer.hbm.xml Set emirlerinin tanımlandığı son bölümdeki dosya.

<?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>

Gördüğünüz gibi, sipariş koleksiyonunu bir set olarak haritalandırdık. Bir setin sırasız benzersiz öğeler koleksiyonu olduğunu unutmayın.

Şimdi, Müşteri sınıfına bakarsanız, aşağıdaki programda gösterildiği gibi Siparişler özelliğinin bir ISet ile tanımlandığını göreceksiniz.

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

Şimdi bu uygulama çalıştırıldığında aşağıdaki çıktıyı göreceksiniz.

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...

Koleksiyondaki öğelerin benzersiz olması gerekmiyorsa, bu koleksiyonda birden çok kez gerçekleşen aynı birincil anahtarla birden fazla siparişiniz olsaydı, bu, aşağıdaki programda gösterildiği gibi bir çanta olarak daha iyi eşleştirilebilirdi.

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

Şimdi, bu uygulamayı çalıştırırsanız bir istisna elde edeceksiniz çünkü müşteri sınıfına bakarsak, siparişlerin C # kodunda ISet olarak işaretlendiğini fark edeceksiniz.

Bu yüzden bunu bir IList olarak değiştirmemiz gerekecek ve sonra burada, yapıcıdaki HashSet'ten List'e geçmemiz gerekecek.

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(); 
   } 
}

Uygulamayı çalıştırdığınızda aynı davranışı göreceksiniz. Ancak, artık aynı koleksiyonda birden çok kez gerçekleşen bir siparişimiz olabilir.

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...

Bu bölümde, Cascade özelliğinin nasıl kullanılacağını ele alacağız. Bir dizi veya öğe koleksiyonunuz veya müşterimiz ve siparişimiz gibi iki sınıf arasında bir ilişkiniz varsa ve yabancı anahtar ilişkiniz varsa. Müşteriyi varsayılan olarak silersek, NHibernate alt nesnelere hiçbir şey yapmaz, bu nedenle o müşteriye ait olanlar ve biz yetim siparişler olabilir.

  • Basamaklı kavramını kullanabilmemiz için yabancı anahtar kısıtlamalarını da ihlal ediyor olabiliriz.

  • Varsayılan olarak, NHibernate işlemleri alt nesnelere basamaklandırmaz.

  • Bunun nedeni, varsayılan bir gönderim adresine sahip bir müşteri gibi ilişkilerinizin olabilmesi ve bu gönderim adresinin birçok farklı müşteri ile paylaşılmasıdır.

  • Dolayısıyla, bu ilişkiyi ille de kademelendirmek istemezsiniz çünkü diğer müşteriler hala ona atıfta bulunuyor.

  • Dolayısıyla, kademeli kavramın tamamı NHibernate'e alt varlıklarını nasıl idare edeceğini söylemektir.

Basamaklama için aşağıdaki gibi farklı seçenekler vardır -

  • none - bu varsayılandır ve basamaksız olduğu anlamına gelir.

  • all - kayıtlar, güncellemeler ve silmeleri basamaklandıracak.

  • save-update - kademeli, kaydeder ve günceller.

  • delete - silme işlemlerini basamaklandıracaktır.

  • all-delete-orphan - Oldukça sık kullanılan ve Hepsi Hariç Tümü ile aynı olan özel bir dosyadır, Sil-yetim satırlarını bulursa bunları da siler.

Varsayılanı şurada belirtebilirsiniz: hbm.xml dosya, böylece bu Hazırda Bekletme eşleme öğesinde varsayılan bir basamak sağlayabilir veya bunu çoktan bire gibi belirli koleksiyonlar ve ilişkiler için de belirtebilirsiniz.

Basit örnek kademelere bir göz atalım, aşağıdaki kodda gösterildiği gibi kaydetmeyi siparişlere manuel olarak kademelendirmemiz gereken programdaki sorunu çözelim.

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(); 
}

Yukarıdaki kod parçacığında, müşteri için tüm siparişleri manuel olarak kaydettiğimizi görebilirsiniz. Şimdi tüm siparişlerin kaydedildiği manuel basamaklı kodu kaldıralım.

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(); 
}

Basamaklı seçeneğini belirtmemiz gerekiyor 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>
  • Artık siparişler tamamen müşteriye aittir. Dolayısıyla, müşteriler veritabanından silinmişse, buradaki uygulamamız, sahipsiz kalmış olanlar da dahil olmak üzere tüm bu siparişleri silmek isteyecektir.

  • Bir silme işlemi sona erecek. Bununla, müşteri kimliğinin sildiğiniz müşteriye eşit olduğu sipariş tablosundan sil diyecektir.

  • Böylece bu silme işlemlerini gerçekten kademelendirebilirsiniz. YaniAll, kaydeder, günceller ve siler.

Şimdi bu uygulamayı çalıştırdığınızda aşağıdaki çıktıyı göreceksiniz.

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...

Gördüğünüz gibi manuel olarak basamaklanan kodu programdan sildik ve uygulamamız hala çalışıyor.

Yani ilişkinize bağlı olarak, bunları basamaklamak isteyebilirsiniz. Şimdi, farklı bir kademeli ilişkiye bakalım. Hadi gidelimOrder.hbm.xml dosya ve bu çoka bir ilişkiyi basamaklandırabiliriz.

<?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>

Yani yeni bir sipariş yaratırsak ve ona eklenen yeni bir müşteri varsa ve biz de bu siparişi kaydedin, bunu kademelendirmek isteyebiliriz. Ancak muhtemelen yapmak istemediğimiz bir şey, ilgili müşteriyi silmek için bir siparişin silinmesidir.

Bu yüzden burada, bir kaydetme güncellemesi yapmak isterdik, bu nedenle bir kaydetme güncellemesi kullanarak, bu müşteriye herhangi bir kaydetme veya güncellemeyi basamaklandıracaktır. Yani, yeni bir müşteri alırsak veya müşteriyi değiştiriyorsak, bunu kademelendirecektir. Silme ise, bunu veritabanından silmez.

Yani uygulamamızı tekrar çalıştırmak, her şey hala beklendiği gibi çalışıyor.

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...

Şimdi uygulamanıza bir göz atmalısınız, varsayılanın Yok olduğunu ve varlığınızın her biri için uygun basamakları ve bu veritabanındaki ilişkilerinizin her birini belirlemek için varlıklar ve bunlar arasındaki ilişkiler hakkında düşünmeniz gerektiğini unutmayın.

Bu bölümde, geç yükleme özelliğini ele alacağız. Varsayılan olarak tamamen farklı bir kavramdır ve NHibernate'in tembel yüklemesi yoktur, örneğin bir müşteriyi yüklerseniz, tüm siparişleri yüklemeyecektir.

  • Sipariş toplama talep üzerine yüklenecektir.

  • İster çoktan bire isterse bir koleksiyon olsun, varsayılan olarak tembel yüklenen herhangi bir ilişkilendirme, bir Open ISession.

  • Oturumunuzu kapattıysanız veya işleminizi gerçekleştirdiyseniz, bu ek nesneleri çekemeyeceği bir tembel yükleme istisnası alabilirsiniz.

  • Tembel yükleme ve gerçekte ne kadar veriye ihtiyacınız olduğuna dikkat etmelisiniz.

  • Tüm bir ilişkilendirme için geç yüklemeyi kapatabilir veya tembel eşittir yanlış koyabilir veya bir getirme stratejisi de belirtebilirsiniz.

İşte Program.cs dosya uygulaması.

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; 
      } 
   } 
}

Bunu anlamak için uygulamayı çalıştıralım ve NHibernate Profiler'a bir göz atalım.

Gördüğünüz gibi, belirli bir müşteri kimliği verilen Müşteriden Seç'e sahibiz ve ayrıca o müşterinin koleksiyonuna gerçekten eriştiğinde başka bir Siparişlerden Seçme tablosuna da sahibiz.

Yani veritabanına 2 gidiş dönüşümüz var. Şimdi, bazen bunu optimize etmek isteriz. Bunu yapmak için gidelimcustomer.hbm.xml dosyasını açın ve bir getirme stratejisi ekleyin ve ondan bir birleştirme getirmesi yapmasını isteyin.

<?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>

Gördüğünüz gibi, uygulamamızda herhangi bir kodu değiştirmediğimizi, az önce customer.hbm.xml. Bu uygulamayı tekrar çalıştıralım, yine aynı şekilde davranıyor. NHibernate Profiler'a bakalım.

  • Daha önce, programın veritabanına iki gidiş-dönüş yolculuğu vardı, şimdi sadece bir tane var ve bunun nedeni burada sol dış birleştirme yapıyor.

  • Müşteri kimliğine göre müşteri tablosu ile sipariş tablosu arasında sol dış birleştirme yaptığını ve bu nedenle tüm bu bilgileri aynı anda yükleyebildiğini görebiliriz.

  • Veritabanına 1 gidiş dönüş kaydettik.

  • Olumsuz tarafı, müşteri bilgilerinin her iki satırda da kopyalanacağı ve bu, bir SQL sol dış birleştirmenin çalışma şeklidir.

  • Bu nedenle, getirme stratejisiyle, biraz daha fazla veri çekiyoruz ve bir gidiş dönüş tasarrufu sağlıyoruz.

Bunu sorgu düzeyinde de yapabilirsiniz, öyleyse hadi Program.cs dosyasını açın ve daha basit yeniden yüklenen örneğe bakın.

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(); 
}

Burada müşteri tarafından bir yükleme yapıyoruz. Şimdi bunu bir sorgu olarak değiştirelim ve aşağıdaki kodda gösterildiği gibi bir bağlantı sorgusu kullanacağız.

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();
}

Getirme stratejisini de customer.hbm.xml dosya.

<?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>

Bu uygulamayı tekrar çalıştıralım ve aşağıdaki çıktıyı göreceksiniz.

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...

Şimdi NHibernate Profiler'a bakalım, bu istekli katılma getirme işleminin bir kez daha gerçekleştiğini görebilirsiniz, ancak bu sefer, sorguya dayalıdır.

Bu bölümde, Ters İlişkiler olan başka bir özelliği ele alacağız. Bu, doğruya tersine eşit olan koleksiyonlarda göreceğiniz eğlenceli bir seçenektir ve aynı zamanda birçok geliştiricinin kafasını karıştırır. Öyleyse bu seçenek hakkında konuşalım. Bunu anlamak için ilişkisel modeli gerçekten düşünmeniz gerekiyor. Diyelim ki, tek bir yabancı anahtar kullanan çift yönlü bir ilişkiniz var.

  • İlişkisel bir bakış açısından, bir yabancı anahtarınız var ve bu hem müşterinin siparişini hem de müşteriye verilen siparişleri temsil ediyor.

  • OO modelinden, bu referansları kullanan tek yönlü ilişkilere sahipsiniz.

  • Veritabanında iki tek yönlü ilişkinin aynı çift yönlü ilişkiyi temsil ettiğini söyleyen hiçbir şey yoktur.

  • Buradaki sorun, NHibernate'in bunu bilmek için yeterli bilgiye sahip olmamasıdır. customer.orders ve order.customer veritabanında aynı ilişkiyi temsil eder.

  • Sağlamak zorundayız inverse equals true bir ipucu olarak, tek yönlü ilişkilerin aynı verileri kullanmasıdır.

  • Kendilerine 2 referansı olan bu ilişkileri kaydetmeye çalışırsak, NHibernate bu referansı iki kez güncellemeye çalışacaktır.

  • Aslında veritabanına fazladan bir gidiş dönüş yapacak ve ayrıca bu yabancı anahtar için 2 güncellemeye sahip olacaktır.

  • Ters eşittir doğru, NHibernate'e ilişkinin hangi tarafının yok sayılacağını söyler.

  • Bunu toplama tarafına uyguladığınızda ve NHibernate her zaman yabancı anahtarı alt nesne tarafından diğer taraftan güncelleyecektir.

  • O zaman bu yabancı anahtarda yalnızca bir güncellememiz var ve bu veriler için ek güncellememiz yok.

  • Bu, yabancı anahtarda bu yinelenen güncellemeleri önlememize olanak tanır ve ayrıca yabancı anahtar ihlallerini önlememize yardımcı olur.

Bir göz atalım customer.cs göreceğiniz dosya AddOrderyöntem ve buradaki fikir şu ki, siparişten müşteriye geri dönen bu geri göstericiye sahibiz ve ayarlanması gerekiyor. Yani bir müşteriye bir sipariş eklendiğinde, o müşterinin arka işaretçisi ayarlanır, aksi takdirde boş olacaktır, bu yüzden nesne grafiğinde bunu birbirine doğru şekilde bağlı tutmak için buna ihtiyacımız var.

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 
   } 
}

İşte Program.cs dosya uygulaması.

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; 
      } 
   } 
}

Bunu veritabanına kaydedecek ve sonra yeniden yükleyecektir. Şimdi uygulamanızı çalıştıralım ve NHibernate Profiler'ı açalım ve gerçekte nasıl kaydettiğini görelim.

3 grup ifademiz olduğunu fark edeceksiniz. İlki müşteriyi ekleyecektir ve bu müşterinin kimliği vurgulanan Kılavuzdur. İkinci ifade, siparişler tablosuna eklenir.

Orada aynı Müşteri Kimliği Kılavuzunun ayarlandığını fark edeceksiniz, bu nedenle yabancı anahtarı ayarlayın. Son ifade, yabancı anahtarı aynı müşteri kimliğine bir kez daha güncelleyecek güncellemedir.

Şimdi sorun şu ki, müşterinin siparişleri var ve siparişlerin müşterisi var, NHibernate'e bunun aslında aynı ilişki olduğunu söylememize imkan yok. Bunu yapma şeklimiz ters eşittir doğrudur.

Öyleyse hadi bizim customer.hbm.xml eşleme dosyası ve tersi aşağıdaki kodda gösterildiği gibi true olarak ayarlayın.

<?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>

Emirleri kaydederken o yabancı anahtarı sipariş tarafından ayarlayacaktır. Şimdi bu uygulamayı tekrar çalıştıralım ve NHibernate profil oluşturucuyu açalım.

Bunların nasıl eklendiğine bakarsak, eki müşteriye ve siparişlere eki alırız, ancak yabancı anahtarın bu yinelenen güncellemesine sahip değiliz çünkü siparişler kaydedilirken güncelleniyor.

  • Şimdi, sadece tek yönlü bir ilişkiniz varsa ve bu ilişkiyi sürdüren küme ise, o zaman ters eşittir doğru çevirirseniz, yabancı anahtarın asla ayarlanmayacağını ve bu öğelerin hiçbir zaman kendilerine sahip olmayacağını not etmelisiniz. veritabanında ayarlanan yabancı anahtarlar.

  • Bire bir ilişkiye bakarsanız, Order.hbm.xml dosya ve tersini ararsanız, aslında ters niteliği yoktur.

  • Her zaman alt öğeden ayarlanır, ancak çoktan çoğa bir koleksiyonunuz varsa, her iki taraftan da ayarlayabilirsiniz.

Bu bölümde, Yükle ve Al özelliklerinin nasıl çalıştığını ve bunları nasıl kullanabileceğimizi ele alacağız. Bunlar, tarafından sağlanan çok benzer iki API'dir.ISession Bir nesneyi birincil anahtarla yüklemek için.

  • Get - nesneyi veya bir boş döndürür.

  • Load - nesneyi döndürür veya bir ObjectNotFoundException.

Şimdi, neden bu iki farklı API'ye sahibiz?

Yük

  • Çünkü Load, veritabanı gidiş dönüşlerini çok daha verimli bir şekilde optimize edebilir.

  • Load aslında bir proxy nesnesi döndürür ve bu Load çağrısını düzenlediğinizde veritabanına erişmesi gerekmez.

  • Bu proxy'ye eriştiğinizde, nesne veritabanında bulunmaz, o noktada bir ObjectNotFoundException oluşturabilir.

Almak

  • Tersine, CLR sınırlamaları nedeniyle Get ile veya Common Language Runtime ve NHibernate derhal veritabanına gitmeli, nesnelerin orada olup olmadığını kontrol etmeli ve yoksa boş döndürmelidir.

  • Bu getirmeyi geciktirme nesne seçeneğine sahip değildir, bu veri tabanına dönüşü daha sonra bir proxy nesnesi döndüremediği için ve kullanıcı gerçekten eriştiğinde bu proxy nesnesini boş değerle değiştirir.

Bunların gerçekte nasıl kullanıldığını ve Get ve Load arasındaki farkı göreceğiniz basit bir örneğe bakalım. Aynı alan sınıflarıyla devam edeceğizCustomers ve Orders ve benzer şekilde son bölümdeki aynı eşleme dosyaları.

Bu örnekte, ilk olarak Get'i aşağıdaki programda gösterildiği gibi kullanacağız.

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; 
      } 
   } 
}

Gördüğünüz gibi iki tane var GuidID'ler, ilki iyi bir ID, veritabanında olduğunu bildiğimiz bir müşterinin ID'sidir. Veritabanında ikinci kimlik yokken. Bu kimliklerin her ikisi de bir parametre olarak aktarılırGet() yöntem ve ardından sonuç konsolda yazdırılır.

Yukarıdaki kod derlendiğinde ve çalıştırıldığında aşağıdaki çıktıyı göreceksiniz.

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...

Müşteri1 verilerinin yazdırıldığını ancak Customer2 verilerinin boş olduğunu görebildiğiniz gibi, bunun nedeni Müşteri2 kaydının veritabanında mevcut olmamasıdır.

Uygulamanızı tekrar çalıştırdığınızda commit ifadesinden önce bir kesme noktası ekleyebilir ve ardından Watch penceresinde her iki müşteriye de bakalım.

Gördüğünüz gibi Müşteri1 verilerinin kullanılabilir durumda olduğu, Müşteri2'nin boş olduğu ve türünün NHibernateDemo.Customer her ikisi için.

Şimdi aşağıdaki kodda gösterildiği gibi aynı örnekte Get yerine Load yöntemini kullanalım.

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; 
      } 
   } 
}

Şimdi bu örneği çalıştıralım ve aşağıdaki istisnanın ekran görüntüsünde görüldüğü gibi atıldığını göreceksiniz.

Şimdi İzleme penceresine bakarsanız, türün her iki nesne için müşteri proxy'si olduğunu göreceksiniz. Ayrıca konsol penceresinde Müşteri1 için aynı verileri görürsünüz.

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

Bu bölümde, insanların kullanacağı diğer bir ortak API'yi NHibernate LINQ sağlayıcısını ele alacağız. ISession'da bir uzatma yöntemi ile erişimi ve imza birQuery <T>. LINQ kullanılırken iki tür sözdizimi vardır -

  • Sorgu Zincirleme Sözdizimi
  • Sorgu Anlama Söz Dizimi

Sorgu Zincirleme Sözdizimi

Aşağıdaki programda gösterildiği gibi yöntem zinciri sözdizimini kullanarak veritabanındaki herhangi bir kayda erişebilirsiniz.

var customer = session.Query<Customer>() .Where(c => c.FirstName == "Laverne")
  • Sorgumuz olduğunu ve ayrıca WHERE cümlesine sahip olduğumuzu görebilirsiniz, ek WHERE cümlecikleri ve benzer şekilde select cümlesine sahip olabilirsiniz.

  • Bu, normal LINQ'da kullanabileceğiniz standart bir yöntem zinciri sözdizimidir.

  • LINQ to Objects veya LINQ to SQL, aşina olabileceğiniz diğer LINQ sağlayıcılarından herhangi biri.

İlk adı Laverne olan müşteriyi alacağımız basit bir örneğe bakalım. Şimdi, ilk adı Laverne olan birden fazla müşterimiz olabilir, bu yüzden sadece ilkini alacağız.

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; 
      } 
   } 
}

Şimdi yukarıdaki kod derlendiğinde ve çalıştırıldığında aşağıdaki çıktıyı göreceksiniz.

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...

Sorgu Anlama Söz Dizimi

Ayrıca, from, where ve select anahtar sözcüklerini kullanan SQL'e çok benzeyen sorgu anlama sözdizimi de vardır.

Öyleyse aynı örneğe bakalım, ancak bu sefer aşağıdaki programda gösterildiği gibi SQL'e çok benzeyen LINQ anlayış sözdizimini kullanıyoruz.

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; 
      } 
   } 
}

Şimdi bu uygulamayı tekrar çalıştıralım ve aşağıdaki çıktıyı göreceksiniz.

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...

Adı H harfiyle başlayan tüm müşterileri alacağımız başka bir örneğe bakalım.

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; 
      } 
   } 
}

Benzer şekilde, sorgu anlama sözdizimi aşağıdaki program gibi görünecektir.

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; 
      } 
   }  
}

Bu uygulamayı tekrar çalıştıralım ve ilk adı H harfiyle başlayan tüm müşterileri göreceksiniz.

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...

Bu bölümde, Hibernate Query Language konusunu ele alacağız. HQL, hem Java'nın Hibernate hem de NHibernate'de paylaşılır.

  • En eski sorgu mekanizmasıdır. Criteria.

  • Çok erken uygulandı ve dize tabanlı bir sorgu API.

  • Şunun üzerinden erişiyorsun ISession CreateQueryve neredeyse SQL'e benzer.

  • Aynı anahtar kelimelerin çoğunu kullanır, ancak basitleştirilmiş bir sözdizimine sahiptir.

  • En yaygın örneklerden biridir, bir sorguyu nasıl gerçekleştireceğinizi arıyorsanız, genellikle HQL örnekleri bulacaksınız.

Aşağıdaki basit bir HQL örneğidir -

var customers = session.CreateQuery("select c from Customer c where c.FirstName = 'Laverne'");
  • Burada müşteriden C'yi seçtiklerini görebilirsiniz, SQL'e çok benziyor. Bu, NHibernate söz konusu olduğunda opak bir dizedir, dolayısıyla bunun dezavantajlarından biri olan çalışma zamanına kadar geçerli bir HQL olup olmadığını bilemezsiniz.

  • LINQ sağlayıcısının güçlü yönlerinden biri, zaman desteğini derleyebilmenizdir.

  • Ancak HQL, sıklıkla kullanılan en esnek sorgu mekanizmalarından biridir. Bunu yapmanın başka bir yolu yoksa bunu HQL'de yapmanın bir yolu olduğu söylenir.

LINQ sorgularımızı bunun yerine HQL kullanarak yeniden oluşturacağımız bir simpe örneğine bakalım. HQL'e erişebilirsiniz.session.CreateQuery ve bir HQL dizesi kullanarak bir parametre olarak aktarın.

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; 
      } 
   } 
}
  • Bu HQL dizesi SQL'e çok benziyor, temel fark, FirstName'in sütun adı değil özellik adı olmasıdır.

  • Yani, ikisi arasında bir tutarsızlık varsa, mülk adını kullanırsınız. Aynı şey, bir tablo adı gibi görünür, ancak aslında seçtiğimiz sınıfın adıdır.

  • Arka uç tablo Müşteriler olarak adlandırılsaydı, yine de Müşteri'yi HQL sorgumuzda kullanırdık.

Hadi bu uygulamayı çalıştıralım ve aşağıdaki çıktıyı göreceksiniz.

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...

HQL kullanarak FirstName H harfi ile başlayan tüm müşterileri alacağımız başka bir basit örneğe bakalım.

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; 
      } 
   } 
}

Şimdi uygulamanızı tekrar çalıştıralım ve göreceksiniz ki adı H ile başlayan tüm müşterilerin bu sorgudan döndüğünü göreceksiniz.

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...

Sipariş sayısı 9'dan büyük olan müşterilerin tüm siparişlerini istemek gibi daha karmaşık şeyler yapabiliriz. Aşağıda aynı HQL sorgusu yer almaktadır.

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

Ayrıca burada bir boyuta veya sayıya veya uzunluğa ihtiyacımız olduğunu da belirtmemiz gerekiyor. HQL'de, yukarıda gösterildiği gibi özel boyut yöntemini kullanma seçeneğimiz var.

Bunu yazmanın diğer yolu, isterseniz c.Orders.sizeve bu tam olarak etkiye sahiptir.

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

Bu uygulamayı çalıştıralım.

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...

9'dan fazla siparişi olan tüm müşterilerin veri tabanından alındığını görebilirsiniz.

Bu bölümde, kriter sorgulama mekanizmasını ele alacağız. NHibernate Query by Criteria API çalışma zamanında ölçüt nesnelerini işleyerek bir sorgu oluşturmanıza olanak sağlar.

  • Bu yaklaşım, kısıtlamaları doğrudan dizge manipülasyonları olmadan dinamik olarak belirlemenize izin verir, ancak HQL'nin esnekliğini veya gücünü büyük ölçüde kaybetmez.

  • Öte yandan, ölçüt olarak ifade edilen sorgular, genellikle HQL'de ifade edilen sorgulardan daha az okunabilirdir.

  • Klasik ölçüt sözdizimi, aşağıdaki programda gösterildiği gibi nesne tabanlı bir sorgu API'sidir.

var customers = session.CreateCriteria<Customer>().Add(Restrictions.Like("FirstName", "H%"));
  • Gördüğünüz gibi, müşteri üzerinde kriterler oluşturmak için bir oturum yapıyoruz ve şimdi bu sorguya kısıtlama nesnesi ekliyoruz.

  • Bu, kullanıcıların belirli seçenekleri seçebileceği, ancak diğerlerini seçemeyeceği sorgu sayfaları için kullanışlıdır.

  • Sorguyu, WHERE yan tümcesinde AND veya OR kullanabileceğiniz HQL veya LINQ yerine ağaç benzeri bir sorgu yapısı olarak oluşturmak daha kolaydır.

  • Bu kriter nesnelerini kullanarak ek kısıtlamalar eklemek daha kolaydır.

Şimdi bir sorgu oluşturacağımız ve kriterler API'sine erişim sağlayacağımız basit bir örneğe göz atalım. createCriteria ve ardından adın H ile başlayacağı bir kısıtlama ekleyin.

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; 
      } 
   } 
}

Yukarıdaki kod derlendiğinde ve çalıştırıldığında aşağıdaki çıktıyı göreceksiniz.

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…

Adı "Laverne" e eşit olan müşteriyi alacağımız başka bir basit örneğe bakalım.

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; 
      } 
   } 
}

Bu uygulamayı tekrar çalıştıralım ve aşağıdaki çıktıyı göreceksiniz.

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...

Şimdi, API kriterlerinin en büyük dezavantajlarından biri, özellik adlarındaki bu opak dizelerdir. Bu nedenle, ilk ad başka bir şey olacak şekilde yeniden düzenlenmişse, yeniden düzenleme aracı opak dizgiyi mutlaka almayacaktır.

Bu bölümde, QueryOver Sorgularını ele alacağız. Aşağıdaki sorguda gösterildiği gibi yöntem zinciri sözdizimini kullanan LINQ'ya daha çok benzeyen yeni bir sözdizimidir.

var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "Laverne");
  • Hala kapakların altındaki kriterler, ancak şimdi sorgularımız güçlü bir şekilde yazılmıştır.

  • Ölçüt sorgusunda gördüğümüz gibi, ilk ad sadece opak bir dizedir, şimdi aslında bir x.FirstName, böylece ilk ad yeniden düzenlenir ve yeniden adlandırılır ve bağlantı stili ölçütü sorgusunda sorgu kullanılarak değiştirilir.

  • Yine de pek çok benzer şey yapabiliriz, ancak sorgu anlama sözdizimini kullanamazsınız, yöntem zinciri sözdizimini kullanmanız gerekir ve bağlantı ile ölçütleri karıştırıp eşleştiremezsiniz.

  • Bir çok sorgu için, API üzerinden sorgu çok kullanışlıdır ve doğrudan Ölçüt kullanmaktan çok nesne sözdizimini anlamak çok daha kolaydır.

İlk adı Laverne olan bir müşteriyi bir sorgu kullanarak alacağımız basit bir örneğe bakalım.

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; 
      } 
   } 
}

Gördüğünüz gibi kapakların altında hala Kriterler var, ancak daha hoş bir sözdizimi.

Yukarıdaki kod derlendiğinde ve çalıştırıldığında, aşağıdaki çıktıyı göreceksiniz.

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...

Dezavantajlarından biri de şunu söylemek istiyoruz diyelim ki FirstName.StartsWith(“A”) aşağıdaki programda gösterildiği gibi.

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

tx.Commit();

Şimdi uygulamayı tekrar çalıştıralım ve bunun bir LINQ sağlayıcısı olmadığını göreceksiniz, çünkü bunun ne olduğunu bilmiyor StartsWith yöntem, yani bir RunTime exception.

İstisna, tanınmayan yöntem çağrısı diyor. Burada apaçık olan şeyi yapıyoruz, ancak bu ille de işe yaramıyor.

Aşağıdaki kodda gösterildiği gibi FirstName'in "A%" ye eşit olması gibi başka bir şey deneyelim.

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

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

Bunu bir kez daha çalıştıralım ve aşağıda gösterildiği gibi herhangi bir sonucu geri almayacağımızı göreceksiniz.

Press <ENTER> to exit...

Bunu neden hiçbir sonuç alamadığımızı anlamak için NHibernate profil oluşturucusuna bir göz atalım.

Gördüğünüz gibi ilk ismin eşit olmayan% A olduğunu. Benzer operatör kullanılarak SQL'de bir% kullanılır. Şimdi aşağıdaki programda gösterildiği gibi WHERE cümlesine bir kısıtlama oluşturmamız gerekiyor.

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

Uygulamanızı tekrar çalıştıralım ve göreceksiniz ki, tüm müşterilerin adı A ile başlıyor.

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

Bu yenisini kullanmak dışında daha önce olduğu gibi çalışır. QueryOversözdizimi. Birçok geliştirici, LINQ sözdiziminin daha ulaşılabilir olduğunu ve çoğu zaman doğru şeyleri yaptığını görmektedir.

LINQ bunu kaldıramazsa, daha uygun olup olmayacağını görmek için HQL veya Kriterlere bakmaya başlayacaksınız.

Sadece size farklı bir sözdizimi verir, bu nedenle Criteria, hem kriter oluşturma hem de QueryOver, NHibernate kullanarak veri tabanından veri çekmenize izin veren başka bir sorgulama mekanizması sağlar.

Bu bölümde, NHibernate'de yerel SQL sorgularının nasıl kullanılacağını ele alacağız. El yazısıyla yazılmış SQL'i birkaç yıldır kullanıyorsanız, ORM'nin alıştığınız ifade ve esnekliğin bir kısmını ortadan kaldıracağından endişe duyabilirsiniz.

  • NHibernate'in güçlü sorgu olanakları, SQL'de yaptığınız hemen hemen her şeyi ve bazı durumlarda daha fazlasını yapmanıza olanak tanır.

  • NHibernate'in kendi sorgu tesislerinin tam olarak istediğinizi yapmasını sağlayamadığınız ender durumlarda.

  • NHibernate, veritabanınızın yerel SQL diyalektini kullanarak nesneleri almanızı sağlar.

NHibernate'deki Yerel SQL sorgularının basit bir örneğine bakalım.

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; 
      } 
   } 
}

Yukarıdaki örnek, CreateSQLQuery() nesnelerin bir listesini geri almak için ve ayrıca sorgunun döndürmesini istediğiniz kök varlık türünün Müşteri olarak belirtildiğini fark edeceksiniz.

Uygulamanızı çalıştıralım ve tüm müşterilerin veritabanından alındığını göreceksiniz.

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

Aşağıda gösterildiği gibi yerel SQL sorgusu yazmanın başka bir yolu.

IList<Customer> customers = session.CreateSQLQuery("SELECT * FROM CUSTOMER")
   .AddScalar("Id", NHibernateUtil.Guid) 
   .AddScalar("FirstName", NHibernateUtil.String) 
   .AddScalar("LastName", NHibernateUtil.String) .List<Customer>();
  • Gördüğünüz gibi, yukarıdaki sorgu SQL sorgu dizesini ve döndürülecek sütunları ve türleri belirtti.

  • Bu, Müşteri tablosundaki her sütun için skaler değerlere sahip bir IList of Object dizileri döndürecektir.

  • Sorgu * kullanıyor olsa bile yalnızca bu üç sütun döndürülür ve listelenen üç sütundan fazlasını döndürebilir.

Başka bir basit örneğe bakalım.

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

Uygulamanızı tekrar çalıştıralım ve aşağıdaki çıktıyı göreceksiniz.

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...

Benzer şekilde, veritabanından veri almak için herhangi bir tür SQL sorgusu belirtebilirsiniz.

Bu bölümde, akıcı NHibernate'i ele alacağız. Fluent NHibernate, haritalamanın başka bir yoludur veya NHibernate'in standart XML eşleme dosyalarına bir alternatif olduğunu söyleyebilirsiniz. XML yazmak yerine(.hbm.xml files)belgeler. Fluent NHibernate'in yardımıyla, güçlü yazılmış C # koduyla eşlemeler yazabilirsiniz.

  • Fluent NHibernate'de eşlemeler, uygulamanızın geri kalanıyla birlikte derlenir.

  • Eşleştirmelerinizi tıpkı uygulama kodunuz gibi kolayca değiştirebilirsiniz ve derleyici herhangi bir yazım hatasında başarısız olur.

  • Adlandırma kurallarını ve diğer birçok şeyi geçersiz kılmak için kalıplar belirleyebileceğiniz geleneksel bir yapılandırma sistemine sahiptir.

  • Nesnelerin nasıl adlandırılacağını da ayarlayabilirsiniz, ardından gerisini Fluent NHibernate halleder.

Yeni bir konsol projesi oluşturarak basit bir örneğe bakalım. Bu bölümde, aşağıdaki resimde gösterildiği gibi basit bir Müşteri tablosuna sahip olduğumuz basit bir veritabanı kullanacağız.

Fluent NHibernate'i kurun

İlk adım, Fluent NHibernate'i başlatmak, Fluent NHibernate paketini kurmaktır. Öyleyse açNuGet Package Manager Console ve aşağıdaki komutu girin.

PM> install-package FluentNHibernate

Başarıyla kurulduktan sonra aşağıdaki mesajı göreceksiniz.

Basit bir Customer model sınıfı ekleyelim ve aşağıdaki program Müşteri sınıfı uygulamasını gösterir.

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; } 
   } 
}

Şimdi akıcı NHibernate kullanarak Mappings oluşturmamız gerekiyor, bu yüzden bir sınıf daha ekleyin CustomerMapprojenizde. CustomerMap sınıfının uygulaması burada.

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"); 
      } 
   }
}

Başka bir sınıf ekleyelim NHibernateHelper içinde farklı yapılandırma ayarları belirleyeceğiz.

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(); 
      } 
   }
}

Şimdi şuraya geçelim Program.cs bir oturum başlatacağımız ve ardından yeni bir müşteri oluşturacağımız ve bu müşteriyi aşağıda gösterildiği gibi veritabanına kaydedeceğimiz dosya.

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(); 
         } 
      } 
   } 
}

Uygulamanızı çalıştıralım ve aşağıdaki çıktıyı göreceksiniz.

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

Gördüğünüz gibi yeni müşteri yaratıldı. Müşteri kaydını görmek için veritabanına gidip Verileri Görüntüle'yi görelim ve 1 Müşteri eklendiğini göreceksiniz.