现在的位置: 首页 > 综合 > 正文

使用NHibernateContrib中的Nullables

2012年12月15日 ⁄ 综合 ⁄ 共 6195字 ⁄ 字号 评论关闭

在NHibernate做字段映射时,一般会把数据库中的数字类型映射为.Net中的值类型,例如SqlServer中的int映射为Int32类型,如果不给此字段赋值,系统将给出默认值,Int32将给出0,而存到数据库中的值也就成了0。虽然我们可以在读取数据时作出处理,发现这样的值当成不合法的数据不予显示。但这样做似乎有些别扭,而且让数据库白白的存些没有用的数据,实在有些浪费。

NHibernateContrib中的Nullables和Nullables.NHibernate给我们提供了解决方法。

  • Nullables: A library of Nullable version of the ValueTypes in net-1.1. It is meant to serve as a bridge until .net-2.0 comes out with their own Nullables.
  • Nullables.NHibernate: A library of NHibernate Types for the Nullables.

    做个最简单的实验,有个表叫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;
                }
            }
        }
    }

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

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

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

    我的测试代码如下

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

  • 抱歉!评论已关闭.