在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
普通方式
{
/// <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;
}
}
}
}
<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 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;
}
}
}
}
<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.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]
{
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]
{
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");
}
}
}