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 — 一个字符
AnsiChar System.Char DbType.AnsiStringFixedLength — 一个字符
Boolean System.Boolean DbType.Boolean
Guid System.Guid DbType.Guid
PersistentEnum System.Enum(枚举) 底层值的 DbType
TrueFalse System.Boolean DbType.AnsiStringFixedLength — 'T' 或 'F'
YesNo System.Boolean DbType.AnsiStringFixedLength — 'Y' 或 'N'
DateTime DateTime DbType.DateTime — 忽略毫秒
Ticks System.DateTime DbType.Int64
TimeSpan System.TimeSpan DbType.Int64
Timestamp System.DateTime DbType.DateTime — 根据数据库支持的精度
Binary System.Byte[] DbType.Binary
BinaryBlob System.Byte[] DbType.Binary
StringClob System.String DbType.String
Serializable 标记有 SerializableAttribute 的任何 System.Object DbType.Binary
CultureInfo System.Globalization.CultureInfo DbType.String — 用于文化的五个字符
Type System.Type DbType.String 包含程序集限定名称

上表详细说明了以下要点。

  • 从简单的数字类型到字符串,可以使用varchar、char等多种方式进行映射,以及字符串 blob 和数据库支持的所有类型的变化。

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

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

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

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

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

现在让我们将 Student 类中的 FirstMidName 更改为 FirstName,我们不会更改 FirstMidName 列,但我们将看到如何告诉 NHibernate 执行此转换。以下是更新后的 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; } 
   }
}

以下是 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 如何执行此转换,请将 name 设置为FirstName,将 column 设置为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("\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(); 
         } 
      } 
   }
}

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

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

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

让我们来看另一个示例,其中我们将在 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 
   } 
}

如您所见,枚举可以有多种不同的值,例如 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 对象资源管理器,右键单击数据库并选择“新建查询…”选项。

New Query

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

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 表,然后创建一个新表。

Create New Table

单击上面显示的“执行”图标。查询成功执行后,您将看到一条消息。

展开数据库和表下拉列表,然后右键单击 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("\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(); 
         } 
      } 
   } 
}

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

Fetch the complete list again

1 Allan Bommer Excellent
2 Jerry Lewis Good

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

Database

选择“查看数据”,您将在 student 表中看到两条记录,如下面的屏幕截图所示。

View Data

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

广告