NHibernate - 数据类型映射

在本章中,我们将介绍映射数据类型。映射实体很简单,实体类始终使用 <class>、<subclass> 和 <joined-subclass> 映射元素映射到数据库表。值类型需要更多的东西,这就是需要映射类型的地方。

NHibernate 能够映射各种数据类型。以下是支持的最常见数据类型的列表。

映射类型 .NET 类型 System.Data.DbType
Int16 System.Int16 DbType.Int16
Int32 System.Int32 DbType.Int32
Int64 System.Int64 DbType.Int64
Single System.Single DbType.Single
Double System.Double DbType.Double
Decimal System.Decimal DbType.Decimal
String System.String DbType.String
AnsiString System.String DbType.AnsiString
Byte System.Byte DbType.Byte
Char System.Char DbType.StringFixedLength—one character
AnsiChar System.Char DbType.AnsiStringFixedLength—one character
Boolean System.Boolean DbType.Boolean
Guid System.Guid DbType.Guid
PersistentEnum System.Enum(an enumeration) DbType for the underlying value
TrueFalse System.Boolean DbType.AnsiStringFixedLength—either 'T' or 'F'
YesNo System.Boolean DbType.AnsiStringFixedLength—either 'Y' or 'N'
DateTime DateTime DbType.DateTime—ignores milliseconds
Ticks System.DateTime DbType.Int64
TimeSpan System.TimeSpan DbType.Int64
Timestamp System.DateTime DbType.DateTime—as specific as the database supports
Binary System.Byte[] DbType.Binary
BinaryBlob System.Byte[] DbType.Binary
StringClob System.String DbType.String
Serializable Any System.Object marked with SerializableAttribute DbType.Binary
CultureInfo System.Globalization.CultureInfo DbType.String—five characters for culture
Type System.Type DbType.String holding the Assembly Qualified Name

上表详细解释了下面提到的指针。

  • 从简单的数字类型到字符串,可以使用varchars、chars等以多种方式映射,以及字符串 blob 和数据库支持的各种类型。

  • 它还能够映射布尔值,既可以映射到使用零和一的字段,也可以映射到包含 true、false 或 T 和 F 的字符字段。

  • 有多种方法可以定义如何映射到后端,数据库中的布尔值。

  • 我们可以处理DateTime的映射,包括和排除时区偏移、夏令时等。

  • 我们还可以映射枚举;我们可以将它们映射到字符串或它们的底层数值。

让我们看一个简单的例子,其中我们在数据库和 Student 类中都有相同的属性名称。

现在让我们将 Student 类中的 FirstMidName 更改为 FirstName,我们不会更改 FirstMidName 列,但我们将了解如何告诉 NHibernate 执行此转换。以下是更新后的学生班。

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

下面是 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>

在此示例中,假设 FirstName 字段是 .NET 字符串,FirstMidName 列是 SQL nvarchar。现在要告诉 NHibernate 如何执行此转换,请将名称设置为 FirstName,将列设置为 FirstMidName,并将映射类型指定为 String,这适用于此特定转换。

以下是 Program.cs 文件实现。

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("
Fetch the complete list again
"); 
               
               foreach (var student in students) { 
                  Console.WriteLine("{0} 	{1} 	{2}", student.ID, student.FirstName,
                     student.LastName); 
               } 
					
               tx.Commit(); 
            } 
				
            Console.ReadLine(); 
         } 
      } 
   }
}

现在,当您运行应用程序时,您将看到以下输出。

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

如您所见,它已将不同的属性名称映射到数据库中的列名称。

让我们看另一个示例,其中我们将在 enum 类型的 Student 类中添加另一个属性。以下是 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 
   } 
}

如您所见,枚举可能具有各种不同的值,例如,优秀、良好、一般、较差和糟糕。

跳转到映射文件,您可以看到映射文件中列出了这些属性中的每一个,包括新添加的 AcademicStanding 属性。

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

现在我们还需要更改数据库,因此请转到 SQL Server 对象资源管理器并右键单击数据库并选择新建查询…选项。

新建查询

它将打开查询编辑器,然后指定以下查询。

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

此查询将首先删除现有的学生表,然后创建一个新表。

创建新表

单击"执行"图标,如上所示。查询成功执行后,您将看到一条消息。

展开数据库和表下拉菜单,然后右键单击 Student 表并选择"视图设计器"。

Table Dropdown

现在,您将看到新创建的表,该表还具有新属性 AcademicStanding。

Academic Standing

让我们添加两条记录,如以下 Program.cs 文件所示。

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("
Fetch the complete list again
");
               
               foreach (var student in students) { 
                  Console.WriteLine("{0} 	{1} 	{2} 	{3}", student.ID,
                     student.FirstName, student.LastName, student.AcademicStanding); 
               } 
					
               tx.Commit(); 
            }
				
            Console.ReadLine(); 
         } 
      } 
   } 
}

现在让我们运行您的应用程序,您将在控制台窗口上看到以下输出。

Fetch the complete list again

1 Allan Bommer Excellent
2 Jerry Lewis Good

现在让我们通过右键单击 Student 表来查看数据库。

Database

选择"查看数据",您将看到 Student 表中的两条记录,如以下屏幕截图所示。

查看数据

您可以看到添加了两条记录,Allan 的 AcademicStanding 为 0,Jerry 的 AcademicStanding 为 1。这是因为在 .Net 中,第一个枚举值默认为 0,如果您查看 StudentAcademicStanding,则为 Excellent。而在 Student.cs 文件中,Good 是第二个,因此它的值为 1。