NHibernate - Mapowanie typów danych
W tym rozdziale zajmiemy się mapowaniem typów danych. Mapowanie jednostek jest proste, klasy jednostek są zawsze mapowane na tabele bazy danych przy użyciu<class>, <subclass>, and <joined-subclass>mapowanie elementów. Typy wartości potrzebują czegoś więcej, czyli tam, gdzie są wymagane typy mapowania.
NHibernate jest w stanie mapować szeroką gamę typów danych. Oto lista najczęściej obsługiwanych typów danych.
| Typ mapowania | Typ .NET | System.Data.DbType | 
|---|---|---|
| Int16 | System.Int16 | DbType.Int16 | 
| Int32 | System.Int32 | DbType.Int32 | 
| Int64 | System.Int64 | DbType.Int64 | 
| Pojedynczy | System.Single | DbType.Single | 
| Podwójnie | System.Double | DbType.Double | 
| Dziesiętny | System.Decimal | DbType.Decimal | 
| Strunowy | System.String | DbType.String | 
| AnsiString | System.String | DbType.AnsiString | 
| Bajt | System.Byte | DbType.Byte | 
| Zwęglać | System.Char | DbType.StringFixedLength - jeden znak | 
| AnsiChar | System.Char | DbType.AnsiStringFixedLength - jeden znak | 
| Boolean | System.Boolean | DbType.Boolean | 
| Guid | System.Guid | DbType.Guid | 
| PersistentEnum | System.Enum (wyliczenie) | DbType dla wartości bazowej | 
| Prawda fałsz | System.Boolean | DbType.AnsiStringFixedLength - „T” lub „F” | 
| Tak nie | System.Boolean | DbType.AnsiStringFixedLength - „Y” lub „N” | 
| DateTime | DateTime | DbType.DateTime - ignoruje milisekundy | 
| Kleszcze | System.DateTime | DbType.Int64 | 
| Okres czasu | System.TimeSpan | DbType.Int64 | 
| Znak czasu | System.DateTime | DbType.DateTime - tak specyficzne, jak obsługuje baza danych | 
| Dwójkowy | System.Byte [] | DbType.Binary | 
| BinaryBlob | System.Byte [] | DbType.Binary | 
| StringClob | System.String | DbType.String | 
| Możliwość serializacji | Dowolny System.Object oznaczony SerializableAttribute | DbType.Binary | 
| CultureInfo | System.Globalization.CultureInfo | DbType.String - pięć znaków dla kultury | 
| Rodzaj | Rodzaj systemu | DbType.String przechowujący kwalifikowaną nazwę zespołu | 
Powyższa tabela szczegółowo wyjaśnia poniższe wskazówki.
- Wszystko, od prostych typów liczbowych po ciągi, które można odwzorowywać na różne sposoby przy użyciu varchars, chars itp., a także ciągowe obiekty blob i wszelkiego rodzaju typy obsługiwane przez bazy danych. 
- Jest również w stanie mapować Booleans, zarówno do pól z zerami i jedynkami, pól znakowych zawierających wartość true, false lub T i F. 
- Istnieje wiele różnych sposobów definiowania tego, w jaki sposób odwzorowuje się to na zaplecze, wartości boolowskie w bazie danych. 
- Możemy obsłużyć mapowanie DateTime, włączając i wyłączając przesunięcia stref czasowych, czas letni itp. 
- Możemy również mapować enumerations; możemy odwzorować je na łańcuchy lub na ich podstawowe wartości liczbowe. 
Przyjrzyjmy się prostemu przykładowi, w którym mamy te same nazwy właściwości zarówno w bazie danych, jak iw klasie Student.
Teraz zmieńmy FirstMidName na FirstName w klasie ucznia, gdzie nie zmienimy kolumny FirstMidName, ale zobaczymy, jak powiedzieć NHibernate, że ma przeprowadzić tę konwersję. Poniżej znajduje się zaktualizowana klasa uczniów.
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; } 
   }
}Oto implementacja pliku mapowania NHibernate.
<?xml version = "1.0" encoding = "utf-8" ?> 
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemoApp" 
   namespace = "NHibernateDemoApp"> 
   
   <class name = "Student">
	
      <id name = "ID"> 
         <generator class = "native"/>
      </id> 
   
      <property name = "LastName"/> 
      <property name = "FirstName" column = "FirstMidName" type = "String"/> 
   </class> 
</hibernate-mapping>W tym przykładzie załóżmy, że pole FirstName to ciąg .NET, a kolumna FirstMidName to SQL nvarchar. Teraz, aby powiedzieć NHibernate, jak przeprowadzić tę konwersję, ustaw nazwę na równąFirstName i kolumna równa FirstMidName i określ typ odwzorowania równy String, który jest odpowiedni dla tej konkretnej konwersji.
Poniżej znajduje się plik Program.cs implementacja plików.
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(); 
         } 
      } 
   }
}Teraz po uruchomieniu aplikacji zobaczysz następujące dane wyjściowe.
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 LewisJak widać, zamapował inną nazwę właściwości na nazwę kolumny w bazie danych.
Spójrzmy na inny przykład, w którym dodamy kolejną właściwość w klasie Student enumrodzaj. Oto implementacja klasy Student.
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 
   } 
}Jak widać, wyliczenie ma wiele różnych wartości, które może mieć, takie jak: Doskonała, Dobra, Dostateczna, Słaba i Okropna.
Przechodząc do pliku mapowania, można zauważyć, że każda z tych właściwości jest wymieniona w pliku mapowania, w tym nowo dodana AcademicStanding własność.
<?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>Teraz musimy również zmienić bazę danych, więc przejdź do Eksploratora obiektów SQL Server i kliknij bazę danych prawym przyciskiem myszy i wybierz opcję Nowa kwerenda….
 
                Otworzy edytor zapytań, a następnie określi poniższe zapytanie.
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) 
);To zapytanie najpierw usunie istniejącą tabelę uczniów, a następnie utworzy nową tabelę.
 
                Kliknij ikonę Wykonaj, jak pokazano powyżej. Po pomyślnym wykonaniu zapytania pojawi się komunikat.
Rozwiń bazę danych i listę rozwijaną Tabela, a następnie kliknij prawym przyciskiem myszy tabelę Ucznia i wybierz Projektanta widoku.
 
                Teraz zobaczysz nowo utworzoną tabelę, która ma również nową właściwość AcademicStanding.
 
                Dodajmy dwa rekordy, jak pokazano poniżej Program.cs plik.
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(); 
         } 
      } 
   } 
}Teraz uruchommy twoją aplikację, a zobaczysz następujące dane wyjściowe w oknie konsoli.
Fetch the complete list again
1 Allan Bommer Excellent
2 Jerry Lewis GoodTeraz spójrzmy do bazy danych, klikając prawym przyciskiem myszy tabelę uczniów.
 
                Wybierz opcję Wyświetl dane, a zobaczysz dwa rekordy w tabeli uczniów, jak pokazano na poniższym zrzucie ekranu.
 
                Możesz zobaczyć, że dodano dwa rekordy, a Allan ma AcademicStanding 0, a Jerry ma AcademicStanding 1. Dzieje się tak, ponieważ w .Net pierwsza wartość wyliczenia domyślnie ma 0, co oznacza, że StudentAcademicStanding. Natomiast w pliku Student.cs Good jest drugim, więc ma wartość 1.