因为NHibernate支持多数据库,就是所谓的分布式事务。因为底层采用的是NH,AR也就很容易的支持了。但是AR的多数据库支持跟NH的配置方式不太一样。NH只需要多写一个NHibernate.Cfg.XML就可以了,然后在数据库配置节点的下面加上使用这个配置的Assembly。而AR则是通过类型来配置不同的数据库设置的。官方的说明文档在:http://www.castleproject.org/index.php/ActiveRecord:Advanced_usage
但是这个文档没有说完全,不分析AR的源码根本就无法配置出来。所以这里再补充一下:
在AR的设计概念里,每种类型可以被分别配置为不同的数据库连接(这比NH将不同的Assembly配置为不同的数据库连接要更灵活,因为同一个Assembly里的类型也可以被保存到不同的数据库中)。那么,如何区分哪些类型是属于哪种数据库呢?
AR采用了抽象公共基类的方式来进行区分,让不同的类型通过继承不同的基类来决定到底使用哪种数据库。举个例子,假如有A、B、C、D四个类,A和B需要保存在SQL SERVER中,而C和D需要保存在ORACLE中。那么就抽象出两个基类M和N,A、B继承自M,C、D则继承自N,然后再这样配置一下:
< activerecord > < config type="Test1ARBase, Castle.ActiveRecord.Tests" > < add key ="hibernate.connection.driver_class"value ="NHibernate.Driver.SqlClientDriver" /> < add key ="hibernate.dialect"value ="NHibernate.Dialect.MsSql2000Dialect" /> < add key ="hibernate.connection.provider"value ="NHibernate.Connection.DriverConnectionProvider" /> < add key ="hibernate.connection.connection_string"value ="Data Source=.;Initial Catalog=test;Integrated Security=SSPI" /> < config> <config type="Castle.ActiveRecord.Tests"> <add key="hibernate.connection.driver_class"value="NHibernate.Driver.OracleClientDriver" /> <add key="hibernate.dialect"value="NHibernate.Dialect.OracleDialect" /> <add key="hibernate.connection.provider"value="NHibernate.Connection.DriverConnectionProvider" /> <add key="hibernate.connection.connection_string"value="Data Source=;User Id=;Password=;" /> config> activerecord>
这里一定要注意这个基类的定义方法(Castle的文档里并没有说明):
这个基类一定是ActiveRecordBase的子类,并且必须是一个抽象类(用abstract定义),而且还不能加上ActiveRecordAttribute这个特性,否则会出现类型未定义PrimaryKey的异常。
附加一点,AR支持默认配置。所有没有找到这个抽象基类的AR实体类型会被自动对应到这个默认的配置上。这也就是为什么在AR的配置中会有source.Add(typeof(ActiveRecordBase), properties);这句的原因。因为ActiveRecordBase就是AR中定义的默认的数据库配置类型。
因此以上的配置可以改为:
< activerecord > < config > < add key ="hibernate.connection.driver_class"value ="NHibernate.Driver.SqlClientDriver" /> < add key ="hibernate.dialect"value ="NHibernate.Dialect.MsSql2000Dialect" /> < add key ="hibernate.connection.provider"value ="NHibernate.Connection.DriverConnectionProvider" /> < add key ="hibernate.connection.connection_string"value ="Data Source=.;Initial Catalog=test;Integrated Security=SSPI" /> config> <config type="Test2ARBase, Castle.ActiveRecord.Tests"> <add key="hibernate.connection.driver_class"value="NHibernate.Driver.OracleClientDriver" /> <add key="hibernate.dialect"value="NHibernate.Dialect.OracleDialect" /> <add key="hibernate.connection.provider"value="NHibernate.Connection.DriverConnectionProvider" /> <add key="hibernate.connection.connection_string"value="Data Source=;User Id=;Password=;" /> config> activerecord>
现在可以去掉Castle.ActiveRecord.Tests.Model.Test1ARBase这个基类。那么,所有未找到配置基类的类型则会自动被保存到默认配置的数据库中,也就是Sql Server中。
把配置设置好了,使用AR的多数据库支持能力还是很爽的。比如你可以简单的这么写:
Entity1 entity1 = new Entity1(); entity1.Create(); //被 保存到SQL SERVER中 Entity2 entity2 = new Entity2(); entity2.Create(); //被 保存到ORACLE中