NHibernate - Załaduj / Pobierz

W tym rozdziale omówimy, jak działają funkcje Load and Get i jak możemy z nich korzystać. Są to dwa bardzo podobne interfejsy API dostarczane przezISession do ładowania obiektu za pomocą klucza podstawowego.

  • Get - zwróci obiekt lub wartość null.

  • Load - zwróci obiekt lub wyrzuci plik ObjectNotFoundException.

Dlaczego mamy te dwa różne interfejsy API?

Załaduj

  • Dzieje się tak, ponieważ Load może znacznie efektywniej zoptymalizować wycieczki w obie strony do bazy danych.

  • Load w rzeczywistości zwraca obiekt proxy i nie musi uzyskiwać dostępu do bazy danych bezpośrednio po wywołaniu wywołania Load.

  • Gdy uzyskujesz dostęp do tego serwera proxy, obiekt nie znajduje się w bazie danych, może w tym momencie zgłosić wyjątek ObjectNotFoundException.

Dostać

  • I odwrotnie, w przypadku Get z powodu ograniczeń środowiska CLR lub Common Language Runtime a NHibernate musi natychmiast przejść do bazy danych, sprawdzić, czy obiekty tam są i zwrócić wartość null, jeśli jej nie ma.

  • Nie ma opcji obiektu opóźniania tego pobierania, tego powrotu do bazy danych w późniejszym czasie, ponieważ nie może zwrócić obiektu proxy i zamienił ten obiekt proxy na wartość null, gdy użytkownik faktycznie uzyskuje do niego dostęp.

Rzućmy okiem na prosty przykład, w którym zobaczysz, jak są one faktycznie używane i jaka jest różnica między Get i Load. Będziemy kontynuować te same klasy domenyCustomers i Orders i podobnie te same pliki mapowań z poprzedniego rozdziału.

W tym przykładzie najpierw użyjemy Get, jak pokazano w poniższym programie.

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

Jak widać, mamy dwa GuidID, pierwszy to dobry identyfikator, to identyfikator klienta, o którym wiemy, że znajduje się w bazie danych. Podczas gdy drugiego identyfikatora nie ma w bazie danych. Oba te identyfikatory są przekazywane jako parametr doGet() a następnie wynik jest drukowany na konsoli.

Kiedy powyższy kod zostanie skompilowany i wykonany, zobaczysz następujące dane wyjściowe.

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

Jak widać, drukowane są dane Customer1, ale dane Customer2 są puste, to znaczy, że rekord Customer2 nie jest dostępny w bazie danych.

Kiedy ponownie uruchomisz aplikację, możemy wstawić punkt przerwania przed instrukcją commit, a następnie przyjrzyjmy się obu klientom w oknie Watch.

Jak widać, dane Customer1 są dostępne, a Customer2 ma wartość NULL, a typ to NHibernateDemo.Customer dla obu.

Teraz użyjmy metody Load zamiast Get w tym samym przykładzie, jak pokazano w poniższym kodzie.

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

Teraz uruchommy ten przykład, a zobaczysz, że zgłaszany jest następujący wyjątek, jak widać na zrzucie ekranu.

Teraz, jeśli spojrzysz na okno Watch, zobaczysz, że typ to customer proxy dla obu obiektów. Te same dane dotyczące Klienta1 są również widoczne w oknie konsoli.

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