В этой главе мы будем говорить о сопоставлении компонентов. В NHibernate компонент представляет собой объект значения . У него нет собственной идентичности.
-
Примером этого может быть денежный объект, в кошельке или кошельке могут быть деньги, но точная идентификация этих денег не имеет значения.
-
У него нет собственного первичного ключа, но сами компоненты хранятся в той же таблице, что и объект-владелец.
Примером этого может быть денежный объект, в кошельке или кошельке могут быть деньги, но точная идентификация этих денег не имеет значения.
У него нет собственного первичного ключа, но сами компоненты хранятся в той же таблице, что и объект-владелец.
Давайте рассмотрим простой пример, в котором у студента есть адрес, который является объектом класса Location, связанного с ним.
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 } }
Теперь нам также необходимо обновить базу данных, выполнив следующий запрос, который сначала удалит таблицу Student, а затем создаст новую таблицу, которая также будет содержать столбец для класса Location.
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) );
Теперь для сопоставления тех столбцов, которые не являются непосредственно частью класса Student, но они являются свойствами класса Location и объекта класса Location, определяется в классе ученика. Нам нужен компонент, чтобы правильно отобразить его. Давайте создадим компонент в файле student.hbm.xml, как показано в следующем коде.
<?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>
Этот компонент является адресом, и он имеет эти различные свойства. С этой информацией NHibernate теперь достаточно, чтобы он мог отобразить это.
Теперь вот файл Program.cs, в котором новый объект студента создается и инициализируется, а затем сохраняется в базе данных. Затем он получит список из базы данных.
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(); } } } }
Теперь мы можем запустить это приложение, а NHibernate может сохранить эти значения в базе данных. Когда вы запустите приложение, вы увидите следующий вывод.
Fetch the complete list again 2 Allan Bommer Poor 123 Street Lahore Punjab Pakistan
Вот значения в базе данных.
Компоненты позволяют нам разделить столбцы в таблице базы данных на отдельный класс.
Другая вещь, на которую следует обратить внимание, это то, что Location является классом, а не сущностью.
Это объект типа значения, и у него нет собственного первичного ключа.
Он сохраняется в той же таблице, что и учащийся, в котором он содержится.
Вот почему мы используем компонент здесь.
Это дает большую гибкость, чтобы изменить наш уровень классов, как наши классы определяются по сравнению с тем, как устроена наша база данных.