施國榮
(國核自儀系統工程有限公司,上海 200241)
核電儀控系統為核電廠提供了各種控制和保護手段以及監控信息,保證了核電廠在正常啟動、停堆、異常和事故工況下能夠安全、可靠、有效地運行。由于核電儀控系統涉及的系統多、工藝復雜、控制設備多,導致控制和測量點的數量龐大。目前,示范項目首堆包括10 個儀控子系統,技術接口61 個,測量信號約2 萬個,每個子系統由5 人共同協作設計。隨著項目數量增多,設計輸入和接口數據成倍增加,各項目之間的輸入和接口數據既有聯系又有區別,在各項目工程任務并行開展的情況下,設計人員會產生質量問題。儀控系統設計團隊除了面臨上述問題外,設計過程受供貨商以及電廠現場變化影響大,各種數據、圖紙修改量極大(示范項目目前設計變更數量約320 個),因此可能出現質量事故的概率也會增加。目前已實現自動化辦公,但所使用的軟件功能有限,不能很好地與目前核電儀控系統設計工作結合,設計人員在應用時需要做大量的非技術性基礎工作,浪費大量時間。例如,設計數據以文件的形式保存,雖然實現了計算機化,但是仍然需要設計人員花費時間驗證文件的有效性、正確性。因此,利用信息化技術,采用更先進的設計、管理工具,提升工作效率,降低人為失誤的概率,才是目前最行之有效的解決辦法。眾所周知,數據持久化使得程序代碼重用性強,即使更換數據庫,只需要更改配置文件,不必重寫程序代碼。此外,持久化技術可以自動優化以減少對數據庫的訪問量,提高程序運行效率。該文將基于NHibernate技術展開研究,通過實現IO清單的數據持久化,與非持久化代碼進行對比,說明程序代碼的可重用性,為工程設計工具開發提供技術支持。
數據庫設計是指對于一個給定的應用環境,構造最優的數據庫模式,建立數據庫及其應用系統,使之能夠有效地存儲數據,滿足各種用戶的應用需求。數據庫設計包括:概念設計、邏輯設計以及物理設計。概念設計是將實際的業務對象通過分類、聚集和概括等方法進行抽象,最終建立概念數據模型。邏輯設計是將概念數據模型設計成具體的數據庫管理系統所能支持的數據模型(即邏輯結構)。物理設計需要根據特定數據庫系統的存儲結構和存取方法等各項物理設計措施,對具體的應用任務選定最合適的物理存儲結構。
工程設計工具用于輔助I/O及硬件設計,維護相關設計數據,以便于應用在對應的工程項目上。設計工具中數據庫用于存儲設計數據信息、版本信息、相關的項目和人員等信息以及設計數據操作記錄。
E-R圖是描述概念數據模型的有效方法之一。圖1為工程師根據實際業務需求分析出的工程設計工具數據庫概念數據模型,圖1展示了用戶、項目、設計數據之間的邏輯關系。邏輯設計階段將概念設計階段得到的概念模型轉換為具體的邏輯結構(即數據表表頭),以I/O清單實體邏輯結構設計結果為例。

圖 1 工程設計工具E-R簡圖
I/O清單表頭,即邏輯結構包括:儀表類型、位號、工藝系統、信號名、信號類型、信號描述、公制量程下限、量程上限公制、量程單位公制、物理量程上限公制、物理量程下限公制、物理量程單位公制、量程下限英制、量程上線英制、量程單位英制、物理量程上限英制、物理量程下限英制、物理量程單位英制、工作介質、工作壓力、工作溫度、供電序列、供電方式、電氣分級、質保分級、機械分級、抗震類別、抗震鑒定、環境鑒定、D-RAP/R分級、環境壓力Min、環境壓力Max、環境溫度Min、環境溫度Max、環境濕度Min、環境濕度Max、外形包絡圖-尺寸、設計壓力、設計溫度、流體介質、工藝要求測量范圍、最低溫度、最高溫度、最高流速、最小流量、最大流量、變送器類型、傳感器類型、過程接口、電氣接口、標定量程、接口類型、I/O類型、行程時間、特殊要求、機組號、房間號、房間描述、測量方式、安裝方式、機柜號、機箱號、卡槽位置、模件類型、通道號。
非持久化方法獲取IO清單數據需要通過SqlConnection類實現。代碼示例如下:
//新建一個數據庫連接
using(SqlConnection conn = new SqlConnection(“Data Source=(localhost);user=develop ;password=123456”)) {
conn.Open();//打開數據庫
SqlCommand cmd = conn.CreateCommand();//創建數據庫連接命令
cmd.CommandText = “SELECT * FROM IOList”;//創建查詢語句,獲取所有I/O清單的數據
SqlDataReader reader = cmd.ExecuteReader();//從數據庫中讀取數據流存入reader中
//從reader中讀取下一行數據,如果沒有數據,reader.Read()返回flase
while (reader.Read()){
int ioListID = reader.GetInt32(reader.GetOrdinal(“IO_LIST_ID”));//獲取I/O清單ID
string signalName = reader.GetString(reader.GetOrdinal(“SIGNAL_NAME”));//獲取I/O信號名}}
上述代碼僅僅獲取I/O清單ID和信號名兩個字段。而I/O清單有65個業務字段,而整個工程設計工具數據庫有100多張表,如果要實現所有表的增刪改查的功能,那么就需要寫大量的SQL代碼。當數據表發生改變時,SQL語句還需要進行相應的調整,代碼的可讀性、可重用性低,開發和維護的成本非常高。此外,SQL查詢優化是非常復雜的,一條看似非常簡單的語句,可能會帶來性能的影響。程序員需要有比較專業的數據庫技能,針對不同的數據庫特點對SQL語句進行優化。
持久化是將程序數據在持久狀態和瞬時狀態間轉換的機制,它主要是將內存中的對象存儲在關系型的數據庫中,當然也可以存儲在磁盤文件中、 XML 數據文件中等。NHibernate是一個面向.Net環境的對象/關系數據庫映射工具。對象關系映射(O/R Mapping,Object Relational Mapping)表示一種技術,用來把對象模型表示的對象映射到基于SQL的關系模型數據結構中去。NHibernate不僅管理.Net類到數據庫表的映射(包括.Net數據類型到SQL數據類型的映射),還提供數據查詢和獲取數據的方法,大幅度減少開發者開發時人工使用SQL和ADO.NET處理數據的時間。NHibernate 采用XML 文件配置方式,每一個實體類對應一個映射文件。體系結構如圖2所示。從圖2中可以看到,NHibernate處于數據庫和應用程序之間,為應用程序提供持久化對象到數據庫的服務。
NHibernate通過使用數據庫和配置文件來為應用程序提供持久化服務,即它使用 NHibernate.properties或XML Mapping兩種配置文件方式把普通對象映射到關系數據庫中的表,從而使得應用程序通過持久化的對象類直接訪問數據庫,而不是必須使用SQL和ADO. NET對數據庫進行操作。

圖2 NHibernate體系結構
NHibernate持久化分為5個步驟,下面以I/O清單表為例來說明持久化方法。為了操作方便和兼容性,需要將漢字表示的邏輯設計用英文字母表示。
3.2.1 配置NHibernate
如圖3所示,在配置文件中需要告訴NHibernate使用的數據庫管理系統、數據庫版本、數據庫實例(包括地址名、實例名、端口號)、用戶名稱以及用戶密碼等。

圖3 NHibernate配置信息
3.2.2 在數據庫中創建I/O清單表
SQL語句如下:
VERSION_ID NUMBER(18) NOT NULL, //版本號
PROJECT_ITEM_ID NUMBER(18),//項目號
STATUS_ID NUMBER(18) NOT NULL,//數據狀態
COMMENTS VARCHAR2(4000 CHAR),//備注
IS_LATEST NUMBER(1) NOT NULL,//是否為最新
IS_VALID NUMBER(1) NOT NULL,//是否校驗
IO_LIST_ID NUMBER(18) NOT NULL,//IO 清單 ID(邏輯主鍵)
小學語文教學當前的發展明顯滯后于教改的進程,要求小學語文教師積極引入新課程理念來改進語文課堂教學,培養學生良好的語文能力。而項目學習則是一種根據教師提供的課題項目而展開自主合作探究的有效學習方式,能夠充分體現學生在知識學習中的主體地位。在小學語文課堂中,教師應該貫徹落實這一理念而開展高效教學,培養學生的自主探究能力和團結協作能力。
FILE_STORE_ID NUMBER(18),//文件 ID
TAG_NO VARCHAR2(128 CHAR) NOT NULL,// 設備位號(業務主鍵)
PROCESS_SYSTEM VARCHAR2(128 CHAR) NOT NULL,//工藝系統
SIGNAL_NAME VARCHAR2(128 CHAR),//信號名
SIGNAL_TYPE VARCHAR2(128 CHAR),//信號類型
SIGNAL_DESCRIPTION VARCHAR2(1024 CHAR),//信號描述
RANGE_MIN NUMBER(18,5),//量程下限
RANGE_MAX NUMBER(18,5),//量程上限
RANGE_UNIT VARCHAR2(128 CHAR),//量程單位
OPERATING_MEDIUM VARCHAR2(128 CHAR),//工作介質
OPERATING_PRES VARCHAR2(128 CHAR),//工作壓力
OPERATING_TEMP VARCHAR2(128 CHAR),//工作溫度
POWER_DIVISION VARCHAR2(128 CHAR),//供電序列
POWER_SUPPLY VARCHAR2(128 CHAR),//供電方式
ELEC_CLASS VARCHAR2(128 CHAR),//電氣分級
WANRRANTY_GRADING VARCHAR2(128 CHAR),//質保分級
MECH_CLASS VARCHAR2(128 CHAR),//機械分級
SEISMIC_CAT VARCHAR2(128 CHAR),//抗震類別
SEISMIC_QUAL VARCHAR2(128 CHAR),//抗震鑒定
ENVIRON_QUAL VARCHAR2(128 CHAR),//環境鑒定
CARD_POSITION VARCHAR2(128 CHAR),//卡槽位置
MODULE_TYPE VARCHAR2(128 CHAR),//模件類型
CHANNEL_NO VARCHAR2(128 CHAR)//通道號
…);
3.2.3 構建持久化的.Net類
代碼如下:
public class IOListObject {
public virtual string TagNO { get; set; } //設備位號
public virtual string ProcessSystem { get; set; }//工藝系統
public virtual string SignalName { get; set; }//型號名
public virtual string SignalType { get; set; }//信號類型
public virtual string SignalDescription { get; set; }//信號描述
public virtual double? RangeMin { get; set; }//量程下限
public virtual double? RangeMax { get; set; }//量程上限
public virtual string RangeUnit { get; set; }//量程單位
public virtual string OperatingMedium { get; set; }//工作介質
public virtual string OperatingPressure { get; set; }//工作壓力
public virtual string OperatingTemperature { get; set; }//工作溫度
public virtual string PowerDivision { get; set; }//供電序列
public virtual string PowerSupply { get; set; }//供電方式
public virtual string ElecClass { get; set; }//電氣分級
public virtual string WanrrantyGrading { get; set; }//質保分級
public virtual string MechClass { get; set; }//機械分級
public virtual string SeismicCategory { get; set; }抗震類別
public virtual string SeismicQual { get; set; }//抗震鑒定
public virtual string EnvironQual { get; set; }//環境鑒定
public virtual string CardPosition { get; set; }//卡槽位置
public virtual string ModuleType { get; set; }//模件類型
public virtual string ChannelNO { get; set; }//通道號…}
3.2.4 創建映射文件(Mapping File)
映射文件用于告訴NHibernate如何從數據表到.Net類的關聯。將需要映射的類、數據表信息編寫到一個映射文件中。
…
3.2.5 使用NHibernate的應用程序編程接口(API,Application Programming Interface)來編程
在類中聲明NHibernate的Factory;在系統初始化的時候加載 XML文件,并創建Factory(即會話工廠,用于提供NHibernate會話環境),代碼如下:
public static void InitializeDataAccessModule(){
Configuration config = new Configuration();
Assembly asm = Assembly.GetAssembly(typeof(DataAccessManager));
string configFile = Path.Combine(Path.GetDirectoryName(asm.CodeBase.Remove(0, 8)), “user-hibernate.cfg.xml”);//加載XML文件
config = config.Configure(configFile);
sessionFactory = config.BuildSessionFactory();//創 建Factroy
isInitialized = true;
}
初始化后NHibernate環境后,可使用 Hql語言編寫具體的插入、修改、刪除、查詢語句,也可直接訪問對象,實現增刪改查操作。如下示例代碼,實現I/O清單的插入和更新:
public I List
ISession session = GetSession();
foreach (IOListVersionObject ilvo in ilvos){
if (ilvo.VersionId.HasValue) {
session.SaveOrUpdate(ilvo);//新建或保存I/O信號
session.Flush();//刷新緩存
}
else
{
session.Save(ilvo);
session.Flush();}}
return ilvos; }
至此,對IO清單進行基于NHibernate的持久化已經實現,通過對比持久化前后程序代碼,可以看出數據持久化后的代碼層次更加的清晰,可重用性提高。但是,NHibernate也存在明顯的不足:為了實現對象與關系模型之間的映射,需要編寫復雜的XML映射文件且容易出錯; NHibernate具有較大的靈活性,體系結構比較復雜,使用難度大;不支持存儲過程、不具備事務處理等數據庫高級功能。這些都需要我們進一步研究與探討,例如,我們發現對象、關系模型以及XML映射文件的字段重復出現,我們是否有辦法可以只設計其中一個,而另外兩個自動生成。