NHibernate的数据库连接机制分析和如何使用外部连接

1.普通数据库连接的分析

在一般情况下我们会让NHibernate应用我们让NHibernate自己管理数据库连接。

我们来看看配置文件中和连接有关的配置信息。

<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">server=.;database=user;uid=sa;pwd=App1234;</property>
<property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>


我们来分析一下这些属性的作用:

connection.provider需配置实现NHibernate.Connection.IConnectionProvider接口的类。
IConnectionProvider定义了创建IDbConnection(用到connection_string)和关闭IDbConnection的功能。
DriverConnectionProvide实现了IConnectionProvider接口,使用IDriver提供的IDbConnection。  
UserSuppliedConnectionProvider实现了IConnectionProvider,使用外部提供的IDbConnection。
ConnectionProviderFactory根据配置文件决定创建何种类型的IConnectionProvider。(让NHibernate自己管理设置DriverConnectionProvide。外部提供连接则无需设置。)





connection.driver_class对应NHibernate.Driver.IDriver接口的类。
描述NHibernate怎么与不同的.NET Data Providers相结合的策略(此处使用了策略模式,关于设计模式可查看Terrylee新版设计模式手册[C#] )。
主要定义了改使用怎样的连接类型和Command类型,以及创建连接和Command的方法(CreateCommand 和 CreateConnection )。
不同的数据库有不同的策略实现。例如:SqlClientDriver提供了访问SQLServer数据的策略(图中省去MySqlDataDriver等多种IDriver)。
 


connection.connection_string提供连接字符串。  

dialect需要配置NHibernate.Dialect.Dialect的子类。 Dialect描述了不同的RDBMS的细节。数据库数据类型和NHibernate数据类型的对应,数据库的函数信息等等。(图中省去多种Dialect)

2.使用外部连接
在某些特殊的时候我们要用到自己提供的连接,例如实现一个连接池管理数据库连接。
注意:使用这种方法的时候切忌不要在一个连接上打开两个并行的ISession

在配置文件中去掉连接的自动管理连接部分的配置.注意dialect不能去掉.

 

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.0">
    
<session-factory name="DDLLY.MyDoc.NHibernateTest.CustomConnect">
        
<!-- 属性 -->
        
<!--<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
        <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
        <property name="connection.connection_string">server=.;database=user;uid=sa;pwd=App1234;</property>
-->
        
<property name="show_sql">true</property>
        
<property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
        
<property name="use_outer_join">true</property>
        
<property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
        
<!-- 映射文件 -->
        
<mapping assembly="DDLLY.MyDoc.NHibernateTest.CustomConnect" />
    
</session-factory>
</hibernate-configuration>

代码中需把OpenSession() 改为使用它的重载函数OpenSession(IDbConnection conn)


对我写的快速入门的 例子进行了一点改动,实现自行提供连接。定义一个CreateConnection的方法创建新的连接。把ISession session = factory.OpenSession()改为ISession session = factory.OpenSession(CreateConnection());

改后代码如下

using System.Collections;
using System.Data.SqlClient;
using NHibernate;
using NHibernate.Cfg;
using NUnit.Framework;
using System.Data;

namespace DDLLY.MyDoc.NHibernateTest.CustomConnect
{
    
/// <summary>
    
/// User测试类
    
/// </summary>

    [TestFixture]
    
public class UserFixture
    
{
        
#region 常量

        
/// <summary>
        
/// 连接字符串
        
/// </summary>

        private const string CONNECTIONSTRING = "server=.;database=user;uid=sa;pwd=App1234;";

        
#endregion


        
#region SetUp和TearDown

        [SetUp]
        
public void SetUp()
        
{
            
//添加名为LLY,密码为123456的用户,因为这是数据库的第一条记录,所以数据库标识为1
            string SetUpSql = "INSERT INTO users([UserName],[Password]) VALUES('LLY','123456')";
            SqlExecuteNonQuery(SetUpSql);
        }


        [TearDown]
        
public void TearDown()
        
{
            
//清空users表,并把标识(identity)清零
            string TearDownSql = "TRUNCATE TABLE users";
            SqlExecuteNonQuery(TearDownSql);
        }


        
#endregion


        
#region 私有方法

        
/// <summary>
        
/// 执行SQL语句
        
/// </summary>
        
/// <param name="sql">SQL语句</param>

        private void SqlExecuteNonQuery(string sql)
        
{
            SqlConnection con 
= new SqlConnection(CONNECTIONSTRING);
            con.Open();
            SqlCommand cmd 
= new SqlCommand();
            cmd.Connection 
= con;
            cmd.CommandText 
= sql;
            cmd.ExecuteNonQuery();
            con.Close();
        }

        
        
/// <summary>
        
/// 创建一个新连接
        
/// </summary>
        
/// <returns></returns>

        private IDbConnection CreateConnection()
        
{
            IDbConnection connection
=new SqlConnection(CONNECTIONSTRING);
            connection.Open();
            
return connection;
        }


        
#endregion


        
#region 测试方法

        
/// <summary>
        
/// 测试读取用户
        
/// </summary>

        [Test]
        
public void TestLoadUser()
        
{
            User user;

            
//配置Configuration
            Configuration cfg = new Configuration().Configure();
            
//创建ISessionFactory
            ISessionFactory factory = cfg.BuildSessionFactory();
            
//打开ISession
            ISession session = factory.OpenSession(CreateConnection());
            
try
            
{
                user 
= session.Load(typeof (User), 1as User;
            }

            
finally
            
{
                session.Close();
            }


            
//************************数据检查*****************************
            
//检查
            Assert.IsNotNull(user, "没有找到ID为1的用户!");
            Assert.AreEqual(
"LLY", user.UserName, "没有找到名字为LLY的用户!");
        }


        
/// <summary>
        
/// 测试查找用户
        
/// </summary>

        [Test]
        
public void TestFindUser()
        
{
            IList userlist;

            
//配置Configuration
            Configuration cfg = new Configuration().Configure();
            
//创建ISessionFactory
            ISessionFactory factory = cfg.BuildSessionFactory();
            
//打开ISession
            string hql = "from User as u where u.UserName='LLY'";
            ISession session 
= factory.OpenSession(CreateConnection());
            
try
            
{
                userlist 
= session.Find(hql);
            }

            
finally
            
{
                session.Close();
            }


            
//************************数据检查*****************************
            
//检查
            Assert.AreEqual(1, userlist.Count, "名字为LLY的用户个数不为1!");
        }


        
/// <summary>
        
/// 测试添加用户
        
/// </summary>

        [Test]
        
public void TestAddUser()
        
{
            User newUser 
= new User();

            
//配置Configuration
            Configuration cfg = new Configuration().Configure();
            
//创建ISessionFactory
            ISessionFactory factory = cfg.BuildSessionFactory();
            
//定义事务
            ITransaction tx = null;
            
//打开ISession
            ISession session = factory.OpenSession(CreateConnection());

            
try
            
{
                
//开始事务
                tx = session.BeginTransaction();
                newUser.UserName 
= "DDL";
                newUser.Password 
= "123456";
                newUser.Email 
= "DDLLY@tom.com";
                
// 保存新用户
                session.Save(newUser);
                tx.Commit();
            }

            
catch (HibernateException ex)
            
{
                
if (tx != null) tx.Rollback();
                
throw ex;
            }

            
finally
            
{
                
//关闭ISession
                session.Close();
            }



            
//************************数据检查*****************************
            IList userlist;
            
string hql = "from User as u where u.UserName='DDL'";
            session 
= factory.OpenSession(CreateConnection());
            
try
            
{
                userlist 
= session.Find(hql);
            }

            
finally
            
{
                session.Close();
            }


            
//检查是否有且仅有一个名称为DDL的用户
            Assert.AreEqual(1, userlist.Count, "名字为DDL的用户个数不为1!");
        }


        
/// <summary>
        
/// 测试删除用户
        
/// </summary>

        [Test]
        
public void TestDeleteUser()
        
{
            IList userlist;
            User user;
            
//配置Configuration
            Configuration cfg = new Configuration().Configure();
            
//创建ISessionFactory
            ISessionFactory factory = cfg.BuildSessionFactory();
            
//定义事务
            ITransaction tx = null;
            
//打开ISession
            ISession session = factory.OpenSession(CreateConnection());
            
try
            
{
                
//开始事务
                tx = session.BeginTransaction();

                user 
= session.Load(typeof (User), 1as User;
                session.Delete(user);

                tx.Commit();
            }

            
catch (HibernateException ex)
            
{
                
if (tx != null) tx.Rollback();
                
throw ex;
            }

            
finally
            
{
                session.Close();
            }


            
//************************数据检查*****************************
            string hql = "from User as u where u.UserName='LLY'";
            session 
= factory.OpenSession(CreateConnection());
            
try
            
{
                userlist 
= session.Find(hql);
            }

            
finally
            
{
                session.Close();
            }


            
//检查
            Assert.AreEqual(0, userlist.Count, "名字为LLY的用户没有被删除!");
        }


        
/// <summary>
        
/// 测试更新用户
        
/// </summary>

        [Test]
        
public void TestUpdateUser()
        
{
            User user;

            
//配置Configuration
            Configuration cfg = new Configuration().Configure();
            
//创建ISessionFactory
            ISessionFactory factory = cfg.BuildSessionFactory();
            
//定义事务
            ITransaction tx = null;
            
//打开ISession
            ISession session = factory.OpenSession(CreateConnection());
            
try
            
{
                
//开始事务
                tx = session.BeginTransaction();

                user 
= session.Load(typeof (User), 1as User;
                user.Password 
= "123";
                session.Update(user);

                tx.Commit();
            }

            
catch (HibernateException ex)
            
{
                
if (tx != null) tx.Rollback();
                
throw ex;
            }

            
finally
            
{
                session.Close();
            }


            
//************************数据检查*****************************
            session = factory.OpenSession(CreateConnection());
            
try
            
{
                user 
= session.Load(typeof (User), 1as User;
            }

            
finally
            
{
                session.Close();
            }


            
//检查
            Assert.IsNotNull(user, "没有找到名字为LLY的用户!");
            Assert.AreEqual(
"123", user.Password, "没有找到名字为LLY的用户!");
        }


        
#endregion

    }

}
共有0个回答