NHibernate - componente de mapeamento

Neste capítulo, falaremos sobre componentes de mapeamento. No NHibernate,component is a value object. Não tem identidade própria.

  • Um exemplo disso seria um objeto de dinheiro, uma bolsa ou carteira pode conter dinheiro, mas a identidade exata desse dinheiro é irrelevante.

  • Ele não tem sua própria chave primária, mas os próprios componentes são persistentes na mesma tabela que o objeto proprietário.

Vamos dar uma olhada em um exemplo simples em que um aluno tem um endereço, que é um objeto de Location class associado a isso.

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

Agora, também precisamos atualizar o banco de dados executando a seguinte consulta, que primeiro eliminará a tabela do aluno e, em seguida, criará uma nova tabela que também conterá uma coluna para a classe Localização.

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) 

);

Agora, para mapear aquelas colunas que não são diretamente uma parte da classe do aluno, mas são propriedades da classe Local e o objeto da classe Local é definido na classe do aluno. Precisamos de um componente para mapeá-lo corretamente. Vamos criar um componente emstudent.hbm.xml arquivo conforme mostrado no código a seguir.

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

Este componente é o Endereço e tem essas propriedades diferentes nele. Com essas informações, o NHibernate agora tem o suficiente para mapear isso.

Agora, aqui está o arquivo Program.cs no qual um novo objeto de aluno é criado e inicializado e então salvo no banco de dados. Em seguida, ele recuperará a lista do banco de dados.

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

Agora podemos rodar este aplicativo e o NHibernate pode salvar esses valores no banco de dados. Ao executar o aplicativo, você verá a seguinte saída.

Fetch the complete list again

2 Allan Bommer Poor 123 Street Lahore Punjab Pakistan

Aqui estão os valores no banco de dados.

Os componentes nos permitem separar as colunas que estão em uma tabela de banco de dados em sua própria classe separada.

  • A outra coisa a observar aqui é porque o local é uma classe, não é uma entidade.

  • É um objeto do tipo valor e não possui sua própria chave primária.

  • Ele é salvo na mesma tabela do Aluno que o contém.

  • É por isso que estamos usando o componente aqui.

  • Isso permite muita flexibilidade para alterar nossa camada de classe, como nossas classes são definidas versus como nosso banco de dados é organizado.