天天看點

ESFramewor使用技巧(2)-- 在插件中使用NHibernate

    我們來讨論一下這種情景,你采用基于ESFramework的4層架構進行應用開發,你分析使用者的需求,并将其分類整理為幾大塊,考慮每一塊使用一個功能插件來完成。在這幾個插件中,有個插件需要通路某個資料庫,并且隻有這個插件需要通路這個資料庫,根據插件的“自治”性質,你不想将本插件中的資料通路“上升蔓延”到應用程式(FS),而是讓它“僅僅”在本插件中,這樣,無論是對FS還是插件都是有好處的--FS自己不需要通路資料庫(日志記錄除外),插件“自治”、而且插件之間互相獨立,整個系統的結構是非常清晰簡單的。

    好了,我們決定在那個需要資料通路的插件中使用NHibernate來實作資料層,但是問題來了--當我們為應用程式添加一個預設的App.Config配置檔案時,在應用程式啟動的時候NHibernate會自動去解析這個檔案的相關配置,而與應用程式不一樣的是,我們也可以為插件添加一個App.Config配置檔案,但是FS在加載這個插件的時候,NHibernate不會去觸碰這個插件對應的App.Config,這樣NHibernate就無法自動完成配置。是以,我們必須手動的解決這個問題。

    幸好,NHibernate.Cfg.Configuration的SetProperties()方法可以允許我們将配置内容添加到NHibernate中。既然,插件的App.Config不起作用,是以幹脆我們用一個自定義的配置檔案好了,其中加入Nhibernate配置:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <ESFrameworke>

    <DataBaseType>Oracle</DataBaseType>

  </ESFrameworke>

  <nhibernate>

    <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />

    <add key="hibernate.connection.driver_class" value="NHibernate.Driver.OracleClientDriver" />

    <add key="hibernate.connection.connection_string" value="user id=jjaj;data source=ORCL;password=gsaj" />

    <add key="hibernate.connection.isolation" value="ReadCommitted"/>

    <add key="hibernate.dialect" value="NHibernate.Dialect.Oracle9Dialect" />

  </nhibernate>

</configuration>

    配置檔案添加之後,我們需要自己手動解析它,使用XPath可以非常容易擷取配置檔案中的Nhibernate配置部分:

        private static IDictionary GetNHibernageCfgs()

        {                

            string xPath = string.Format("/configuration/nhibernate/add") ;

            XmlNodeList list = XmlDoc.SelectNodes(xPath) ;

            IDictionary dic = new Hashtable() ;

            foreach(XmlNode node in list)

            {

                dic.Add(node.Attributes.Item(0).InnerText ,node.Attributes.Item(1).InnerText) ;

            }

            return dic ;            

        }

    當插件被加載的時候的時候,插件讀取這個配置并初始化NHibernate的SessionFactory。但是如何切入插件加載的時刻了?你一定還記得,插件IAddin接口中的OnLoading方法--就是它了,在其中加入類似下面的代碼:

                IDictionary dic   = GetNHibernageCfgs() ;

                Configuration config = new Configuration();

                config.SetProperties(dic) ;                        

                config =  config.AddAssembly("BusinessManagerAddin") ;

                ISessionFactory factory  = config.BuildSessionFactory();    

    本文解決的隻是一個簡單的在Dll(插件也是Dll)中進行NHibernate配置的問題,但是本文更是為了說明一種思想,那就是,在最小的範圍内解決問題(如果可以的話),而不是将問題蔓延到更大的範圍。上面所說的插件中的NHibernate配置、初始化完全可以在FS中進行,但是如果這樣做,不僅使得FS難于了解(因為FS根本不會使用這個配置的SessionFactory),而且FS還需要将SessionFactory引用通過某種方式傳遞到插件中,這違反插件“自治”原則,使得FS不再單純,而且與插件的關系也将日趨複雜。

附錄(2006.06.07):如何使用CodeSmith協助NHibernate實體類與.hbm.xml檔案自動生成

    今天重裝機後,重裝了CodeSmith,結果忘記了如何讓CodeSmith協助NHibernate,摸索了一會才搞定,現記錄下來作以後參考。

(1)CodeSmith使用 V2.5

(4)NHibernate配置示例:

    <configSections>

         <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />            

    </configSections>     

    <nhibernate>

        <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />

        <add key="hibernate.connection.driver_class" value="NHibernate.Driver.OracleClientDriver" />

        <add key="hibernate.connection.connection_string" value="user id=XTGL;data source=ORCL;password=GSGL" />

        <add key="hibernate.connection.isolation" value="ReadCommitted"/>

        <add key="hibernate.dialect" value="NHibernate.Dialect.Oracle9Dialect" />

    </nhibernate>