NHibernate - Mappatura dei tipi di dati

In questo capitolo, tratteremo i tipi di dati di mappatura. Il mapping delle entità è semplice, le classi di entità vengono sempre associate alle tabelle del database utilizzando<class>, <subclass>, and <joined-subclass>elementi di mappatura. I tipi di valore hanno bisogno di qualcosa di più, che è dove sono richiesti i tipi di mappatura.

NHibernate è in grado di mappare un'ampia varietà di tipi di dati. Ecco l'elenco dei tipi di dati più comuni supportati.

Tipo di mappatura Tipo .NET System.Data.DbType
Int16 System.Int16 DbType.Int16
Int32 System.Int32 DbType.Int32
Int64 System.Int64 DbType.Int64
Single System.Single DbType.Single
Doppio System.Double DbType.Double
Decimale System.Decimal DbType.Decimal
Corda System.String DbType.String
AnsiString System.String DbType.AnsiString
Byte System.Byte DbType.Byte
Char System.Char DbType.StringFixedLength: un carattere
AnsiChar System.Char DbType.AnsiStringFixedLength: un carattere
Booleano System.Boolean DbType.Boolean
Guid System.Guid DbType.Guid
PersistentEnum System.Enum (un'enumerazione) DbType per il valore sottostante
Vero falso System.Boolean DbType.AnsiStringFixedLength: "T" o "F"
Si No System.Boolean DbType.AnsiStringFixedLength: "Y" o "N"
Appuntamento Appuntamento DbType.DateTime: ignora i millisecondi
Zecche System.DateTime DbType.Int64
Arco di tempo System.TimeSpan DbType.Int64
Timestamp System.DateTime DbType.DateTime: specifico come il database supporta
Binario System.Byte [] DbType.Binary
BinaryBlob System.Byte [] DbType.Binary
StringClob System.String DbType.String
Serializzabile Qualsiasi System.Object contrassegnato con SerializableAttribute DbType.Binary
CultureInfo System.Globalization.CultureInfo DbType.String: cinque caratteri per le impostazioni cultura
genere Tipo di sistema DbType.String contenente il nome qualificato dell'assembly

La tabella sopra riportata spiega in dettaglio i suggerimenti indicati di seguito.

  • Tutto, dai semplici tipi numerici alle stringhe, che possono essere mappate in vari modi usando varchars, chars ecc. così come i BLOB di stringhe e tutta la varietà di tipi supportati dai database.

  • È anche in grado di mappare Booleans, sia ai campi che utilizzano zeri che uno, campi carattere che contengono vero, falso o T e F.

  • Esiste un'ampia varietà di modi per definire il modo in cui viene eseguito il mapping ai valori booleani di back-end nel database.

  • Possiamo gestire la mappatura di DateTime, inclusi ed esclusi offset di fuso orario, ora legale, ecc.

  • Possiamo anche mappare enumerations; possiamo mapparli a stringhe o ai loro valori numerici sottostanti.

Diamo uno sguardo a un semplice esempio in cui abbiamo gli stessi nomi di proprietà sia nel database che nella classe Student.

Ora cambiamo FirstMidName in FirstName nella classe student, dove non cambieremo la colonna FirstMidName, ma vedremo come dire a NHibernate di eseguire questa conversione. Di seguito è riportata la classe studentesca aggiornata.

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

Ecco l'implementazione del file di mappatura 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>

In questo esempio, si supponga che il campo FirstName sia una stringa .NET e che la colonna FirstMidName sia un file SQL nvarchar. Ora per dire a NHibernate come eseguire questa conversione, imposta il nome uguale aFirstName e colonna uguale a FirstMidName e specificare il tipo di mappatura uguale a String, appropriato per questa particolare conversione.

Quello che segue è un file Program.cs implementazione del file.

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

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

namespace NHibernateDemoApp { 

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

Ora quando esegui la tua applicazione, vedrai il seguente output.

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

Come puoi vedere, ha mappato il nome della diversa proprietà al nome della colonna nel database.

Diamo un'occhiata a un altro esempio in cui aggiungeremo un'altra proprietà nella classe Student di enumgenere. Ecco l'implementazione della classe 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 
   } 
}

Come puoi vedere, l'enumerazione ha una varietà di valori diversi che può eventualmente avere come, eccellente, buono, giusto, scarso e terribile.

Saltando al file di mappatura, puoi vedere che ognuna di queste proprietà è elencata nel file di mappatura, incluso il file appena aggiunto AcademicStanding proprietà.

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

Ora dobbiamo anche cambiare il database, quindi vai in Esplora oggetti di SQL Server e fai clic con il pulsante destro del mouse sul database e seleziona l'opzione Nuova query….

Si aprirà l'editor delle query e quindi specificherà la query seguente.

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

Questa query eliminerà prima la tabella studente esistente e quindi creerà una nuova tabella.

Fare clic sull'icona Esegui come mostrato sopra. Una volta che la query viene eseguita con successo, viene visualizzato un messaggio.

Espandere il database e l'elenco a discesa Tabella, quindi fare clic con il pulsante destro del mouse sulla tabella Studente e selezionare Visualizza Designer.

Ora vedrai la tabella appena creata, che ha anche la nuova proprietà AcademicStanding.

Aggiungiamo due record come mostrato di seguito Program.cs file.

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

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

namespace NHibernateDemoApp { 

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

Ora eseguiamo la tua applicazione e vedrai il seguente output nella finestra della tua console.

Fetch the complete list again

1 Allan Bommer Excellent
2 Jerry Lewis Good

Ora esaminiamo il database facendo clic con il pulsante destro del mouse sulla tabella degli studenti.

Seleziona Visualizza dati e vedrai i due record nella tabella studenti come mostrato nello screenshot seguente.

Puoi vedere che vengono aggiunti due record e Allan ha AcademicStanding 0 e Jerry ha AcademicStanding 1. Questo perché in .Net il primo valore di enumerazione per impostazione predefinita ha 0, che è Eccellente se guardi StudentAcademicStanding. Considerando che nel file Student.cs Good è il secondo, quindi ha un valore di 1.