由於NHibernate是被設計應用在許多不同環境中的,因此它存在很多配置參數。幸運的是,這些參數大多都有合理的默認值,而且NHibernate發布的時候伴隨着一個App.config 例子(可在src\NHibernate.Test找到),這個例子已經包含了了很多配置信息。你通常只要把這個文件放如你的項目中然后定制它就行了。
編程式配置
一個NHibernate.Cfg.Configuration 實例表示一個完整的應用程序里面的類型和SQL數據庫mapping信息的集合。Configuration 被用來創建一個(不變的)ISessionFactory。mapping信息編譯自各種各樣的XML mapping文件。
你可以通過直接實例化的方式獲得Configuration 實例。這是一個從兩個XML配置文件中的mapping信息建立數據庫模型的例子:
Configuration cfg = new Configuration() .AddFile("Item.hbm.xml") .AddFile("Bid.hbm.xml");
另一個方式(在某些情況下更合適)是讓NHibernate從嵌入的資源中加載mapping文件:
Configuration cfg = new Configuration() .AddClass(typeof(NHibernate.Auction.Item)) .AddClass(typeof(NHibernate.Auction.Bid));
NHibernate 會查找NHibernate.Auction.Item.hbm.xml 和NHibernate.Auction.Bid.hbm.xml 的mapping文件,這些XML文件都是嵌入在程序集中的資源。這種方式避免了文件名稱硬代碼。
其他方式(可能是最好的方式)就是讓NHibernate加載包含在程序集中的所有mapping文件:
Configuration cfg = new Configuration()
.AddAssembly( "NHibernate.Auction" );
NHibernate會查找程序集中所有以.hbm.xml結尾的資源文件。這種方式避免了文件名稱硬代碼並且確保了在程序集中的mapping文件能夠被添加。
如果使用類似於Visual Studio .NET or NAnt 的工具來生成程序集,要保證.hbm.xml 文件都要是以嵌入的資源編譯到程序集中。
Configuration 也定義了一些可選的屬性:
IDictionary props = new Hashtable(); ... Configuration cfg = new Configuration() .AddClass(typeof(NHibernate.Auction.Item)) .AddClass(typeof(NHibernate.Auction.Bind)) .SetProperties(props);
Configuration 只是一個配置的時候產生的對象,一旦一個ISessionFactory 實例被建立的時候,他就會被回收。
獲得一個ISessionFactory
當所有的mapping都被Configuration解析之后,應用程序會得到一個生產ISession 實例的工廠。這個工廠會被所有線程共享:
ISessionFactory sessions = cfg.BuildSessionFactory();
然而,NHibernate的確會讓你生成一個以上的ISessionFactory,這個是使用多個數據庫的時候很有用。
用戶提供的ADO.NET 連接
在一個由用戶提供的ADO.NET 連接中,一個ISessionFactory會開啟一個ISession 。這個設計讓應用程序能夠自由獲得它想要的ADO.NET 連接:
IDbConnection conn = myApp.GetOpenConnection(); ISession session = sessions.OpenSession(conn); // do some data access work
要注意,應用程序不能通過在同一個ADO.NET 連接中同時打開兩個ISessions 。
NHibernate 提供的 ADO.NET 連接
Alternatively, you can have the ISessionFactory open connections for you. The ISessionFactory must be provided with ADO.NET connection properties in one of the following ways:
-
Pass an instance of IDictionary mapping property names to property values to Configuration.SetProperties().
-
Add the properties to a configuration section in the application configuration file. The section should be named nhibernate and its handler set to System.Configuration.NameValueSectionHandler.
-
Include <property> elements in a configuration section in the application configuration file. The section should be named hibernate-configuration and its handler set to NHibernate.Cfg.ConfigurationSectionHandler. The XML namespace of the section should be set to urn:nhibernate-configuration-2.2.
-
Include <property> elements in hibernate.cfg.xml (discussed later).
If you take this approach, opening an ISession is as simple as:
另外,你也可以讓ISessionFactory 為你打開連接。ISessionFactory 必須通過下面幾種方式中的一種獲得ADO.NET 連接屬性:
- 傳一個IDictionary 實例,給Configuration.SetProperties().
- 在應用程序配置文件中把屬性添加到configuration section 中。這個節點必須叫做nhibernate 並且它的handler是System.Configuration.NameValueSectionHandler。
- 包含在配置文件的configuration section 的<property>屬性中。
包含在hibernate.cfg.xml 中<property> 屬性中(等會會提及)。
如果你使用這方式,那么打開一個ISession 就這么簡單:
ISession session = sessions.OpenSession(); // open a new Session // do some data access work, an ADO.NET connection will be used on demand
NHibernate屬性名稱和語法都在NHibernate.Cfg.Environment中定義。我們現在說一說ADO.NET 連接配置的重要設定。
如果你設置了下面的屬性,NHibernate將會使用一個ADO.NET data provider 來獲得(或者保存)連接。
Table 3.1. NHibernate ADO.NET 屬性
屬性名稱
通途
connection.provider_class 自定義 IConnectionProvider 實現.
例如. full.classname.of.ConnectionProvider 如果Provider在 NHibernate中創建, 或者 full.classname.of.ConnectionProvider, assembly 如果使用一個自定義的 IConnectionProvider 接口實現,它不包含在NHibernate中. 默認值是 NHibernate.Connection.DriverConnectionProvider.
connection.driver_class 自定義的 IDriver類型, 如果使用 DriverConnectionProvider.
full.classname.of.Driver 如果Driver在 NHibernate中創建, 或者full.classname.of.Driver, assembly 如果使用不包含在NHibernate中的IDriver 實現.
這個通常是不需要的,大多數情況下方言會使用合理的默認值來完成IDriver的配置。參見特定的方言API文檔來或者這些默認值。
connection.connection_string 獲得連接的連接字符串。 connection.connection_string_name 用來獲得連接的連接字符串的名字(定義在配置文件的<connectionStrings>中) connection.isolation 設置事務的隔離級別。檢查System.Data.IsolationLevel 來獲得具體值,同時檢查數據庫文檔來確定這個級別是被支持的。
例如:Chaos, ReadCommitted, ReadUncommitted, RepeatableRead, Serializable, Unspecified
connection.release_mode Specify when NHibernate should release ADO.NET connections. See
設置NHibernate 什么時候釋放ADO.NET 連接。參見Section 11.7, “Connection Release Modes”
例如:auto (默認) | on_close | after_transaction
需要注意的是,這個配置僅僅影響ISessionFactory.OpenSession返回的ISession。對於從ISessionFactory.GetCurrentSession, ICurrentSessionContext 接口實現的ISession,參見Section 2.3, “Contextual Sessions”.
command_timeout 設置由NHibernate生成的IDbCommands 的默認超時值。 adonet.batch_size 設置使用batch更新時的batch的大小。如果設置成0,就會關閉這個功能。參見Section 19.6, “Batch updates”. 下面是一個在web.config配置數據庫連接屬性的例子:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" /> </configSections> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> <session-factory> <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property> <property name="connection.connection_string"> Server=(local);initial catalog=theDb;Integrated Security=SSPI </property> <property name="connection.isolation">ReadCommitted</property> </session-factory> </hibernate-configuration> <!-- other app specific config follows --> </configuration>
NHibernate依賴ADO.NET data provider 實現的連接池。
你可以通過實現NHibernate.Connection.IConnectionProvider接口來自定義獲得ADO.NET 連接的方式。你可以通過設置connection.provider_class來選擇一個自定義的實現。
可選的配置屬性
有許多其他的屬性可以控制運行時的NHibernate的行為,所有的這些配置都是可選的,並且有一些合理的默認值。
系統級別的屬性只能夠通過手動設置NHibernate.Cfg.Environment 類或者在應用程序配置文件中的<nhibernate>中定義。這些屬性不能使用Configuration.SetProperties設定,不能在配置文件的<hibernate-configuration>中定義。
Table 3.2. NHibernate Configuration Properties
屬性名稱
用途
dialect
NHibernate方言類型名稱——可以讓NHibernate使用某些數據庫的特性
例如:full.classname.of.Dialect, assemblydefault_schema
在生成的SQL中確定某個表空間下面的表名稱。
例如:SCHEMA_NAMEmax_fetch_depth
為單一終點(single-ended )的關聯(one-to-one, many-to-one)設置外連(outer join)的最大深度。設置成0就會禁用外連。
例如:建議在0到3之間use_reflection_optimizer
Enables use of a runtime-generated class to set or get properties of an entity or component instead of using runtime reflection (System-level property). The use of the reflection optimizer inflicts a certain startup cost on the application but should lead to better performance in the long run. You can not set this property in hibernate.cfg.xml or <hibernate-configuration> section of the application configuration file.
eg. true | false
bytecode.provider
Specifies the bytecode provider to use to optimize the use of reflection in NHibernate. Use null to disable the optimization completely, lcg to use lightweight code generation.
eg. null | lcg
cache.provider_class
The classname of a custom ICacheProvider.
eg. classname.of.CacheProvider, assembly
cache.use_minimal_puts
Optimize second-level cache operation to minimize writes, at the cost of more frequent reads (useful for clustered caches).
eg. true | false
cache.use_query_cache
Enable the query cache, individual queries still have to be set cacheable.
eg. true | false
cache.query_cache_factory
The classname of a custom IQueryCacheFactory interface, defaults to the built-in StandardQueryCacheFactory.
eg. classname.of.QueryCacheFactory, assembly
cache.region_prefix
A prefix to use for second-level cache region names.
eg. prefix
query.substitutions
Mapping from tokens in NHibernate queries to SQL tokens (tokens might be function or literal names, for example).
eg. hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC
query.linq_provider_class
The classname of a custom LINQ provider class, one that implements INhQueryProvider. The default is DefaultQueryProvider
eg. true | false
show_sql
將所有SQL語句輸出到控制台。
例如. true | false
hbm2ddl.auto
Automatically export schema DDL to the database when the ISessionFactory is created. With create-drop, the database schema will be dropped when the ISessionFactory is closed explicitly.
eg. create | create-drop
hbm2ddl.keywords
Automatically import reserved/keywords from the database when the ISessionFactory is created.
none : disable any operation regarding RDBMS KeyWords
keywords : imports all RDBMS KeyWords where the Dialect can provide the implementation of IDataBaseSchema.
auto-quote : imports all RDBMS KeyWords and auto-quote all table-names/column-names .
eg. none | keywords | auto-quote
use_proxy_validator
允許或者禁用代理接口或者類的驗證。默認是允許。
例如: true | false
transaction.factory_class
自定義ITransactionFactory 實現的類名,默認值是內置的AdoNetWithDistributedTransactionFactory
例如. classname.of.TransactionFactory, assembly
default_flush_mode
默認的 FlushMode,默認值是Unspecified
例如: Unspecified | Never | Commit | Auto | AlwaysSQL方言
你應當根據你的數據庫類型將dialect屬性設置成對應的NHibernate.Dialect.Dialect 子類。這不是必要的,除非你想要使用native或者sequence主鍵生成策略或者樂觀鎖(例如:ISession.Lock()或者IQuery.SetLockMode())。然而,如果你確定了一個方言,NHibernate就會用適當的默認值來配置上面的屬性來節省你的時間。
Table 3.3. NHibernate SQL Dialects (dialect)
RDBMS Dialect Remarks DB2 NHibernate.Dialect.DB2Dialect DB2 for iSeries (OS/400) NHibernate.Dialect.DB2400Dialect Ingres NHibernate.Dialect.IngresDialect PostgreSQL NHibernate.Dialect.PostgreSQLDialect PostgreSQL 8.1 NHibernate.Dialect.PostgreSQL81Dialect This dialect supports FOR UPDATE NOWAIT available in PostgreSQL 8.1. PostgreSQL 8.2 NHibernate.Dialect.PostgreSQL82Dialect This dialect supports IF EXISTS keyword in DROP TABLE and DROP SEQUENCE available in PostgreSQL 8.2. MySQL 3 or 4 NHibernate.Dialect.MySQLDialect MySQL 5 NHibernate.Dialect.MySQL5Dialect Oracle NHibernate.Dialect.Oracle8iDialect Oracle 9i NHibernate.Dialect.Oracle9iDialect Oracle 10g, Oracle 11g NHibernate.Dialect.Oracle10gDialect Oracle 12c NHibernate.Dialect.Oracle12cDialect Sybase Adaptive Server Enterprise 15 NHibernate.Dialect.SybaseASE15Dialect Sybase Adaptive Server Anywhere 9 NHibernate.Dialect.SybaseASA9Dialect Sybase SQL Anywhere 10 NHibernate.Dialect.SybaseSQLAnywhere10Dialect Sybase SQL Anywhere 11 NHibernate.Dialect.SybaseSQLAnywhere11Dialect Microsoft SQL Server 7 NHibernate.Dialect.MsSql7Dialect Microsoft SQL Server 2000 NHibernate.Dialect.MsSql2000Dialect Microsoft SQL Server 2005 NHibernate.Dialect.MsSql2005Dialect Microsoft SQL Server 2008 NHibernate.Dialect.MsSql2008Dialect Microsoft SQL Server 2012 NHibernate.Dialect.MsSql2012Dialect Microsoft SQL Server Compact Edition NHibernate.Dialect.MsSqlCeDialect Microsoft SQL Server Compact Edition 4 NHibernate.Dialect.MsSqlCe40Dialect Firebird NHibernate.Dialect.FirebirdDialect Set driver_class to NHibernate.Driver.FirebirdClientDriver for Firebird ADO.NET provider 2.0. SQLite NHibernate.Dialect.SQLiteDialect Set driver_class to NHibernate.Driver.SQLite20Driver for System.Data.SQLite provider for .NET 2.0. 在NHibernate.Dialect 名稱空間中還包含其他的可用方言。
外連接獲取
如果你的數據庫支持ANSI或者Oracle風格的外連接,外連接抓取可能提高性能,因為可以限制和數據庫交互的數量(代價是數據庫自身進行了更多的工作)。外連接抓取允許你在一個SELECT語句中就可以得到一個由many-to-one, one-to-many 或者 one-to-one 連接構成的對象圖。
默認情況下的抓取在葉對象,擁有代理的對象或者產生對自身的引用時終止。
對一個特定關聯來說,可以通過在XML映射文件中設置outer-join屬性可以控制是否開啟抓取功能。
可以設置max_fetch_depth為0來禁用全局的外連接抓取。設置為1或者更大的數值將啟用one-to-one和many-to-one關聯(這些關聯被map成fetch="join")中的外連接抓取。
參見Section 19.1, “Fetching strategies” 來獲得更多信息。
在NHibernate 1.0,outer-join 特性有相似的作用,這個特性現在已經變不建議使用,我們推薦使用的是fetch。
自定義ICacheProvider
你可以通過實現NHibernate.Cache.ICacheProvider接口來繼承一個二級緩存。你可以通過設置cache.provider_class來自定義實現。
參見Section 19.2, “The Second Level Cache” 來獲得更多信息。
查詢語言替換
你可以使用 query.substitutions 來定義NHibernate新的查詢短語. 例如
query.substitutions true=1, false=0
會在生成的SQL中把短語true和false替換成整數值。
query.substitutions toLowercase=LOWER
這可以讓你重新命名SQL的LOWER 函數。
日志
通過使用Apache log4net,NHibernate 可以記錄很多事件。
你可以從http://logging.apache.org/log4net/ 下載log4net。要使用log4net,你要在app.config或者web.config中配置log4net節點。在src/NHibernate.Test工程中有一個配置的例子
我們強烈建議你熟悉NHibernate's的log信息。NHibernate's的很多工作都會盡量留下詳盡卻易讀的log信息。這個是很重要的定位問題的方式。同樣的,別忘記啟用上文提到的SQL日志(show_sql),這個是你查找性能問題的第一步。
實現一個INamingStrategy接口
NHibernate.Cfg.INamingStrategy 接口允許你為數據庫對象和schema elements(譯注,不會翻譯)指定一個“命名標准”
你可以提供一個從自動生成數據庫。這個特性能個幫你你減少冗長的mapping文件,減少煩人的重復(例如,TBL_ 前綴)。
你可以在添加mapping之前通過調用Configuration.SetNamingStrategy()來指定一個不同的策略:
The interface NHibernate.Cfg.INamingStrategy allows you to specify a "naming standard" for database objects and schema elements.
You may provide rules for automatically generating database identifiers from .NET identifiers or for processing "logical" column and table names given in the mapping file into "physical" table and column names. This feature helps reduce the verbosity of the mapping document, eliminating repetitive noise (TBL_ prefixes, for example). The default strategy used by NHibernate is quite minimal.
You may specify a different strategy by calling Configuration.SetNamingStrategy() before adding mappings:
ISessionFactory sf = new Configuration() .SetNamingStrategy(ImprovedNamingStrategy.Instance) .AddFile("Item.hbm.xml") .AddFile("Bid.hbm.xml") .BuildSessionFactory();
XML配置文件
一個其他的配置方法是在一個叫做hibernate.cfg.xml的文件中進行一個完整的配置。這個文件可以被用來替換應用程序配置文件中的<nhibernate;> 或者 <hibernate-configuration>。
XML配置文件默認需要在你的應用程序目錄下,這里是一個例子:
<?xml version='1.0' encoding='utf-8'?> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> <!-- an ISessionFactory instance --> <session-factory> <!-- properties --> <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property> <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property> <property name="connection.connection_string">Server=localhost;initial catalog=nhibernate;User Id=;Password=</property> <property name="show_sql">false</property> <property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property> <!-- mapping files --> <mapping resource="NHibernate.Auction.Item.hbm.xml" assembly="NHibernate.Auction" /> <mapping resource="NHibernate.Auction.Bid.hbm.xml" assembly="NHibernate.Auction" /> </session-factory> </hibernate-configuration>
配置NHibernate就會如此簡單:
ISessionFactory sf = new Configuration().Configure().BuildSessionFactory();
你也可以選一個不同的XML配置文件,使用:
ISessionFactory sf = new Configuration() .Configure("/path/to/config.cfg.xml") .BuildSessionFactory();