在NHibernate做字段映射时,一般会把数据库中的数字类型映射为.Net中的值类型,例如SqlServer中的int映射为Int32类型,如果不给此字段赋值,系统将给出默认值,Int32将给出0,而存到数据库中的值也就成了0。虽然我们可以在读取数据时作出处理,发现这样的值当成不合法的数据不予显示。但这样做似乎有些别扭,而且让数据库白白的存些没有用的数据,实在有些浪费。
NHibernateContrib中的Nullables和Nullables.NHibernate给我们提供了解决方法。
做个最简单的实验,有个表叫studnets,有三个字段
[id] [int] IDENTITY (1, 1) NOT NULL , //PRIMARY KEY
[name] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
[age] [int] NULL
普通方式
using
System;
namespace NHTest
{
/// <summary>
/// Student
/// </summary>
public class Student
{
public Student()
{
}
private int m_ID;
private string m_Name = null ;
private int m_Age;
public int ID
{
get
{
return m_ID;
}
}
public string Name
{
get
{
return m_Name;
}
set
{
m_Name = value;
}
}
public int Age
{
get
{
return m_Age;
}
set
{
m_Age = value;
}
}
}
}
namespace NHTest
{
/// <summary>
/// Student
/// </summary>
public class Student
{
public Student()
{
}
private int m_ID;
private string m_Name = null ;
private int m_Age;
public int ID
{
get
{
return m_ID;
}
}
public string Name
{
get
{
return m_Name;
}
set
{
m_Name = value;
}
}
public int Age
{
get
{
return m_Age;
}
set
{
m_Age = value;
}
}
}
}
<?
xml version="1.0" encoding="utf-8"
?>
< hibernate-mapping xmlns ="urn:nhibernate-mapping-2.0" >
< class name ="NHTest.Student,NHTest" table ="students" >
< id name ="m_ID" column ="id" type ="Int32" unsaved-value ="0" access ="field" >
< generator class ="native" ></ generator >
</ id >
< property name ="Name" column ="name" type ="String" ></ property >
< property name ="Age" column ="age" type ="Int32" ></ property >
</ class >
</ hibernate-mapping >
< hibernate-mapping xmlns ="urn:nhibernate-mapping-2.0" >
< class name ="NHTest.Student,NHTest" table ="students" >
< id name ="m_ID" column ="id" type ="Int32" unsaved-value ="0" access ="field" >
< generator class ="native" ></ generator >
</ id >
< property name ="Name" column ="name" type ="String" ></ property >
< property name ="Age" column ="age" type ="Int32" ></ property >
</ class >
</ hibernate-mapping >
使用Nullables
using
System;
using Nullables.NHibernate;
using Nullables;
namespace NHTest
{
/// <summary>
/// 允许age为Nullables的Student
/// </summary>
public class StudentN
{
public StudentN()
{
}
private int m_ID = 0 ;
private string m_Name = null ;
private NullableInt32 m_Age = null ;
public int ID
{
get
{
return m_ID;
}
}
public string Name
{
get
{
return m_Name;
}
set
{
m_Name = value;
}
}
public NullableInt32 Age
{
get
{
return m_Age;
}
set
{
m_Age = value;
}
}
}
}
using Nullables.NHibernate;
using Nullables;
namespace NHTest
{
/// <summary>
/// 允许age为Nullables的Student
/// </summary>
public class StudentN
{
public StudentN()
{
}
private int m_ID = 0 ;
private string m_Name = null ;
private NullableInt32 m_Age = null ;
public int ID
{
get
{
return m_ID;
}
}
public string Name
{
get
{
return m_Name;
}
set
{
m_Name = value;
}
}
public NullableInt32 Age
{
get
{
return m_Age;
}
set
{
m_Age = value;
}
}
}
}
<?
xml version="1.0" encoding="utf-8"
?>
< hibernate-mapping xmlns ="urn:nhibernate-mapping-2.0" >
< class name ="NHTest.StudentN,NHTest" table ="students" >
< id name ="m_ID" column ="id" type ="Int32" unsaved-value ="0" access ="field" >
< generator class ="native" ></ generator >
</ id >
< property name ="Name" column ="name" type ="String" ></ property >
< property name ="Age" column ="age" type ="Nullables.NHibernate.NullableInt32Type,Nullables.NHibernate" ></ property >
</ class >
</ hibernate-mapping >
< hibernate-mapping xmlns ="urn:nhibernate-mapping-2.0" >
< class name ="NHTest.StudentN,NHTest" table ="students" >
< id name ="m_ID" column ="id" type ="Int32" unsaved-value ="0" access ="field" >
< generator class ="native" ></ generator >
</ id >
< property name ="Name" column ="name" type ="String" ></ property >
< property name ="Age" column ="age" type ="Nullables.NHibernate.NullableInt32Type,Nullables.NHibernate" ></ property >
</ class >
</ hibernate-mapping >
我的测试代码如下
using
System;
using System.Data;
using System.Data.SqlClient;
using System.Collections;
using NUnit.Framework;
using NHibernate;
using NHibernate.Cfg;
namespace NHTest
{
[TestFixture]
public class TestCase
{
[SetUp]
public void SetUp()
{
}
[TearDown]
public void TearDown()
{
SqlConnection con = new SqlConnection();
con.ConnectionString = " server=.;database=NHTest;uid=sa;pwd=sa; " ;
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = " delete from students " ; // 清空数据库
try
{
con.Open();
cmd.ExecuteNonQuery();
}
finally
{
con.Close();
}
}
[Test]
public void TestStudentN()
{
Configuration cfg = new Configuration().Configure(); // 直接读取hibernate.cfg.xml中的配置
ISessionFactory factory = cfg.BuildSessionFactory();
ITransaction tran = null ;
try
{
ISession session = factory.OpenSession();
tran = session.BeginTransaction();
StudentN newStudent = new StudentN();
newStudent.Name = " DDL " ; // 没有给newStudent设置Age
session.Save(newStudent);
tran.Commit();
}
catch (Exception ex)
{
tran.Rollback();
throw ex;
}
ISession session1 = factory.OpenSession();
IList lists = session1.Find( " from StudentN S where S.Name='DDL' " );
Assert.AreEqual( 1 ,lists.Count, " 名为DDL的学生没有找到 " );
StudentN student = (StudentN)lists[ 0 ];
Assert.AreEqual( " DDL " ,student.Name, " 没找到名为LLY的student " );
// Assert.AreEqual(student.Age,null); // 学生的Age不为null,不过Age的HasValue属性为false
Assert.IsFalse(student.Age.HasValue, " Age有值 " );
}
[Test]
public void TestStudent()
{
Configuration cfg = new Configuration().Configure(); // 直接读取hibernate.cfg.xml中的配置
ISessionFactory factory = cfg.BuildSessionFactory();
ITransaction tran = null ;
try
{
ISession session = factory.OpenSession();
tran = session.BeginTransaction();
Student newStudent = new Student();
newStudent.Name = " LLY " ; // 没有给newStudent设置Age
session.Save(newStudent);
tran.Commit();
}
catch (Exception ex)
{
tran.Rollback();
throw ex;
}
ISession session1 = factory.OpenSession();
IList lists = session1.Find( " from Student S where S.Name='LLY' " );
Assert.AreEqual( 1 ,lists.Count, " 名为LLY的学生没有找到 " );
Student student = (Student)lists[ 0 ];
Assert.AreEqual( " LLY " ,student.Name, " 没找到名为LLY的student " );
Assert.AreEqual( 0 ,student.Age, " 学生年龄没有设置默认值0 " );
}
}
}
using System.Data;
using System.Data.SqlClient;
using System.Collections;
using NUnit.Framework;
using NHibernate;
using NHibernate.Cfg;
namespace NHTest
{
[TestFixture]
public class TestCase
{
[SetUp]
public void SetUp()
{
}
[TearDown]
public void TearDown()
{
SqlConnection con = new SqlConnection();
con.ConnectionString = " server=.;database=NHTest;uid=sa;pwd=sa; " ;
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = " delete from students " ; // 清空数据库
try
{
con.Open();
cmd.ExecuteNonQuery();
}
finally
{
con.Close();
}
}
[Test]
public void TestStudentN()
{
Configuration cfg = new Configuration().Configure(); // 直接读取hibernate.cfg.xml中的配置
ISessionFactory factory = cfg.BuildSessionFactory();
ITransaction tran = null ;
try
{
ISession session = factory.OpenSession();
tran = session.BeginTransaction();
StudentN newStudent = new StudentN();
newStudent.Name = " DDL " ; // 没有给newStudent设置Age
session.Save(newStudent);
tran.Commit();
}
catch (Exception ex)
{
tran.Rollback();
throw ex;
}
ISession session1 = factory.OpenSession();
IList lists = session1.Find( " from StudentN S where S.Name='DDL' " );
Assert.AreEqual( 1 ,lists.Count, " 名为DDL的学生没有找到 " );
StudentN student = (StudentN)lists[ 0 ];
Assert.AreEqual( " DDL " ,student.Name, " 没找到名为LLY的student " );
// Assert.AreEqual(student.Age,null); // 学生的Age不为null,不过Age的HasValue属性为false
Assert.IsFalse(student.Age.HasValue, " Age有值 " );
}
[Test]
public void TestStudent()
{
Configuration cfg = new Configuration().Configure(); // 直接读取hibernate.cfg.xml中的配置
ISessionFactory factory = cfg.BuildSessionFactory();
ITransaction tran = null ;
try
{
ISession session = factory.OpenSession();
tran = session.BeginTransaction();
Student newStudent = new Student();
newStudent.Name = " LLY " ; // 没有给newStudent设置Age
session.Save(newStudent);
tran.Commit();
}
catch (Exception ex)
{
tran.Rollback();
throw ex;
}
ISession session1 = factory.OpenSession();
IList lists = session1.Find( " from Student S where S.Name='LLY' " );
Assert.AreEqual( 1 ,lists.Count, " 名为LLY的学生没有找到 " );
Student student = (Student)lists[ 0 ];
Assert.AreEqual( " LLY " ,student.Name, " 没找到名为LLY的student " );
Assert.AreEqual( 0 ,student.Age, " 学生年龄没有设置默认值0 " );
}
}
}