📅  最后修改于: 2020-11-19 05:36:35             🧑  作者: Mango
在本章中,我们将讨论映射组件。在NHibernate中, component是一个值对象。它没有自己的身份。
这样的例子是货币对象,钱包或钱包中可能有货币,但是该货币的确切身份无关紧要。
它没有自己的主键,但组件本身与拥有对象在同一表中是持久性的。
让我们看一个简单的示例,其中学生有一个地址,该地址是与之关联的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类中定义的。我们需要一个组件来正确映射它。让我们在student.hbm.xml文件中创建一个组件,如以下代码所示。
该组件是地址,并且具有这些不同的属性。有了这些信息,NHibernate现在具有足够的空间来实际映射它。
现在是Program.cs文件,在其中创建并初始化一个新的Student对象,然后将其保存到数据库中。然后它将从数据库中检索列表。
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();
x.Dialect();
});
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().ToList();
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是一个类,而不是一个实体。
这是一个值类型对象,没有自己的主键。
它与包含它的Student保存在同一表中。
这就是为什么我们在这里使用组件。
这提供了很大的灵活性来更改我们的类层,如何定义类以及如何布置数据库。