NHibernate Step by Step(二) 單表操作
接著(zhù)第一期,我們繼續。
為了方便學(xué)習測試,從今天開(kāi)始我將使用MS Test來(lái)進(jìn)行測試,這樣就避免了在一個(gè)Console工程里不停地添加、注釋代碼了。
提示:為了在VS2005IDE中獲得NHibernate配置文件的代碼提示,請將你的$NHibernate\src\NHibernate下的nhibernate-configuration-2.0.xsd、nhibernate-mapping-2.0.xsd拷貝到\Program Files\Microsoft Visual Studio 8\Xml\Schemas下,這樣當你編輯配置文件或者映射文件時(shí),你將得到完整的代碼提示。
VS2003請拷貝到\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\schemas\xml下。
NHibernat內部使用log4net來(lái)進(jìn)行日志操作,今天我們將在配置文件中添加log4net的配置,這樣我們在測試的時(shí)候將可以清楚地看到NHibernate是如何進(jìn)行工作的。
應用配置文件修改如下:
CODE:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System,Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<nhibernate>
<add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
<add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
<add key="hibernate.connection.connection_string" value="Server=localhost;Initial Catalog=NHibernate;Integrated Security=SSPI" />
<add key="hibernate.connection.isolation" value="ReadCommitted"/>
<add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" />
<add key="show_sql" value="true" />
</nhibernate>
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>
</configuration>
請注意添加:
CODE:
<add key="show_sql" value="true" />
關(guān)于log4net的使用,我們這里不做詳細的講解,有興趣的請參考如下地址:
http://logging.apache.org/log4net/
接著(zhù),我們在上次的工程組中添加一個(gè)名為T(mén)est1的測試項目,將其中的不需要的手動(dòng)測試去掉。請注意:除了NHibernate\Model引用外,還需要添加如下3個(gè)引用:
log4net,System.Data,System.Xml.
修改代碼如下:
CODE:
using System;
using System.Text;
using System.Collections;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NHibernate;
using NHibernate.Cfg;
using log4net;
using log4net.Config;
using Test.Model;
namespace Test1
{
/**//// <summary>
/// Summary description for UnitTest1
/// </summary>
[TestClass]
public class UnitTest1
{
static ISessionFactory factory;
static ILog logger;
ISession session;
public UnitTest1()
{
}
Additional test attributes#region Additional test attributes
[ClassInitialize()]
public static void MyClassInitialize(TestContext testContext)
{
XmlConfigurator.Configure();
logger = LogManager.GetLogger(typeof(Test1.UnitTest1));
Configuration config = new Configuration().AddAssembly("Test.Model");
factory = config.BuildSessionFactory();
}
[ClassCleanup()]
public static void MyClassCleanup() { }
[TestInitialize()]
public void MyTestInitialize()
{
session = factory.OpenSession();
}
[TestCleanup()]
public void MyTestCleanup()
{
session.Close();
}
#endregion
}
}
我們在測試的開(kāi)始對Configuration\SessionFactory\Log進(jìn)行初始化。在每一個(gè)Test的開(kāi)始獲取一個(gè)新的session,每一個(gè)Test結束后即關(guān)閉session。
添加如下一個(gè)Get測試:
CODE:
[TestMethod]
public void TestRead()
{
Person person = (Person)session.Get(typeof(Person), 1);
Assert.IsTrue(person.Name == "Jackie Chan");
}
我們在前面曾經(jīng)插入一條名為“Jackie Chan”的記錄,現在在Test Manager中選中TestRead,運行,ok,Passed!
我們使用了session.Get來(lái)獲取記錄,方法如下:
object Get(Type clazz,object id);
很簡(jiǎn)單,一目了然。
我們切換到Test Results窗口,雙擊測試成功的TestRead方法,這時(shí)將會(huì )有一個(gè)詳細的測試結果顯示出來(lái),NHibernate將使用我們指定的log4net來(lái)輸出詳細信息,我們仔細觀(guān)察:
CODE:
2006-04-15 13:52:13,000 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - opened session
2006-04-15 13:52:13,015 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - loading [Person#1]
2006-04-15 13:52:13,015 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - attempting to resolve [Person#1]
2006-04-15 13:52:13,015 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - object not resolved in any cache [Test.Model.Person#1]
2006-04-15 13:52:13,015 [AdpaterExeMgrThread1] DEBUG NHibernate.Persister.EntityPersister [(null)] - Materializing entity: Test.Model.Person#1
2006-04-15 13:52:13,078 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.BatcherImpl [(null)] - Opened new IDbCommand, open IDbCommands :1
2006-04-15 13:52:13,078 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.BatcherImpl [(null)] - Building an IDbCommand object for the SqlString: SELECT person0_.id as id0_, person0_.name as name0_ FROM Person person0_ WHERE person0_.id=:id
2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] DEBUG NHibernate.Type.Int32Type [(null)] - binding '1' to parameter: 0
2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] INFO NHibernate.Loader.Loader [(null)] - SELECT person0_.id as id0_, person0_.name as name0_ FROM Person person0_ WHERE person0_.id=@p0
2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] DEBUG NHibernate.SQL [(null)] - SELECT person0_.id as id0_, person0_.name as name0_ FROM Person person0_ WHERE person0_.id=@p0
2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] DEBUG NHibernate.SQL [(null)] - @p0 = '1'
2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] DEBUG NHibernate.Connection.DriverConnectionProvider [(null)] - Obtaining IDbConnection from Driver
2006-04-15 13:52:13,859 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.BatcherImpl [(null)] - Opened Reader, open Readers :1
2006-04-15 13:52:13,859 [AdpaterExeMgrThread1] DEBUG NHibernate.Loader.Loader [(null)] - processing result set
2006-04-15 13:52:13,875 [AdpaterExeMgrThread1] DEBUG NHibernate.Loader.Loader [(null)] - result row: 1
2006-04-15 13:52:13,875 [AdpaterExeMgrThread1] DEBUG NHibernate.Loader.Loader [(null)] - Initializing object from DataReader: 1
2006-04-15 13:52:13,875 [AdpaterExeMgrThread1] DEBUG NHibernate.Loader.Loader [(null)] - Hydrating entity: Test.Model.Person#1
2006-04-15 13:52:13,906 [AdpaterExeMgrThread1] DEBUG NHibernate.Type.StringType [(null)] - returning 'Jackie Chan' as column: name0_
2006-04-15 13:52:13,906 [AdpaterExeMgrThread1] DEBUG NHibernate.Loader.Loader [(null)] - done processing result set (1 rows)
2006-04-15 13:52:13,937 [AdpaterExeMgrThread1] DEBUG NHibernate.Driver.NHybridDataReader [(null)] - running NHybridDataReader.Dispose()
2006-04-15 13:52:13,937 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.BatcherImpl [(null)] - Closed Reader, open Readers :0
2006-04-15 13:52:13,937 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.BatcherImpl [(null)] - Closed IDbCommand, open IDbCommands :0
2006-04-15 13:52:13,937 [AdpaterExeMgrThread1] DEBUG NHibernate.Loader.Loader [(null)] - total objects hydrated: 1
2006-04-15 13:52:13,953 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - resolving associations for: [Test.Model.Person#1]
2006-04-15 13:52:13,953 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - done materializing entity [Test.Model.Person#1]
2006-04-15 13:52:13,953 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - initializing non-lazy collections
2006-04-15 13:52:13,953 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - closing session
2006-04-15 13:52:13,953 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - disconnecting session
2006-04-15 13:52:13,953 [AdpaterExeMgrThread1] DEBUG NHibernate.Connection.ConnectionProvider [(null)] - Closing connection
2006-04-15 13:52:13,968 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - transaction completion
在其中,我們可以發(fā)現:
CODE:
2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] DEBUG NHibernate.SQL [(null)] - SELECT person0_.id as id0_, person0_.name as name0_ FROM Person person0_ WHERE person0_.id=@p0
2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] DEBUG NHibernate.SQL [(null)] - @p0 = '1'
對了,就是這里,NHibernate替我們構造了一條sql語(yǔ)句,并添加一個(gè)參數,然后將我們在代碼中賦的id值1來(lái)填充,這樣,一條完整的可以執行的sql語(yǔ)句產(chǎn)生了。
請注意:在產(chǎn)生sql語(yǔ)句的前面,NHibernate構造了一個(gè)IDBCommand,然后在sql語(yǔ)句產(chǎn)生完全后,獲取連接,通過(guò)一個(gè)DataReader來(lái)填充Persion對象給我們使用,這就是NHibernate替我們做的事,是不是很簡(jiǎn)單???(真的很簡(jiǎn)單嗎??看看源代碼吧?。。?br>
請仔細研究輸出的日志。
如法炮制,我們添加另外3個(gè)Test,完成單個(gè)表的全部CRUD操作,如下完整代碼:
CODE:
[TestMethod]
public void TestCreate()
{
Person person = new Person();
person.Name = "Jackie Chan";
ITransaction trans = session.BeginTransaction();
try
{
session.Save(person);
trans.Commit();
Assert.IsTrue(person.Id > 0);
}
catch (Exception ex)
{
trans.Rollback();
Assert.Fail(ex.Message);
}
}
[TestMethod]
public void TestUpdate()
{
Person person = (Person)session.Get(typeof(Person), 1);
person.Name = "Jet Li";
ITransaction trans = session.BeginTransaction();
try
{
session.Save(person);
trans.Commit();
Assert.IsTrue(person.Name == "Jet Li");
}
catch (Exception ex)
{
trans.Rollback();
Assert.Fail(ex.Message);
}
}
[TestMethod]
public void TestRead()
{
Person person = (Person)session.Get(typeof(Person), 1);
Assert.IsTrue(person.Name == "Jackie Chan");
}
[TestMethod]
public void TestDelete()
{
Person person = (Person)session.Get(typeof(Person), 1);
ITransaction trans = session.BeginTransaction();
try
{
session.Delete(person);
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback();
Assert.Fail(ex.Message);
}
}
Delete的方法如下:
void Delete(object obj);
直接傳入需要delete的對象即可。
好了,基本的操作都完成了,是不是很Easy?
好了,這一篇就講這么多,我們下次再接著(zhù)練習。
Step by Step,顧名思義,是一步一步來(lái)的意思,整個(gè)教程我將貫徹這一理念。
任何建議或者批評,請e:abluedog@163.com