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


SetUp和TearDown#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), 1) as 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), 1) as 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), 1) as 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), 1) as User;
}
finally

{
session.Close();
}

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

#endregion
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?