房澤臣 陳川琳 蔡紅明 吳志林
(南京理工大學機械工程學院 南京 210094)
槍彈參數數據庫管理是槍彈一體化設計與分析系統的基礎功能之一,為槍彈的設計、分析提供支撐。該系統基于.NET FrameWork平臺,采用C#語言編寫程序,并采用SQL Server 2012數據庫。其中,槍彈參數數據庫管理的核心程序為批量操作程序。
批量操作程序的設計目的是方便用戶高效地管理、維護各個槍彈參數子數據庫,是數據庫管理系統的核心功能。大部分文獻采取SqlCommand對象對數據庫進行添加和修改操作,但使用SqlCommand對象需針對不同的數據表編寫相應的CommnadText,并且SqlCommand對象中參數要與數據表中的字段名一一對應,如果字段名較多,需人工添加參數[1]。
本文所述槍彈參數數據庫含11個數據庫表,數百個字段名,如果采用SqlCommand對象逐條操作記錄的方式,不僅使用人員的工作效率較低,而且開發人員也需投入較大精力開發大量的界面和繁瑣冗長的代碼。本研究基于上述兩點原因,采用SqlDataAdapter適配器類進行設計,旨在提供代碼簡潔、移植性好、運行穩定、使用方便的槍彈參數數據庫批量操作程序。
SqlDataAdapter數據適配器類是.NET Framework Data Provider for SQL Server數據提供程序中的核心類之一[2]。SqlDataAdapter適配器類可使用SQL Sever中的數據填充到內存數據集DataSet或內存數據表 DataTable,并根據 DataSet、DataTable及DataRow[]中的RowState屬性的更改自動生成相應SQL命令更新SQL Sever數據庫。
ADO.NET提供鏈接模式和無鏈接模式兩種數據庫訪問模式[3~6]。鏈接模式主要依靠 SqlCommand命令類實現數據庫操作,無鏈接模式主要依靠SqlDataAdapter數據適配器類實現數據庫操作。SqlCommand對象直接向數據庫服務器發送SQL命令實時操作數據庫,數據處理邏輯通常時間較短,不利于實現復雜的處理邏輯[7~8]。SqlDataAdapter數據適配器類,操作對象為DataSet、DataTable及DataRow[],在提交之前可像操作數據庫那樣對DataSet、DataTable及DataRow[]中的數據記錄進行修改、驗證、取消等操作,當數據記錄符合用戶要求后再進行提交,更容易實現邏輯復雜、數據安全的數據庫操作。
在鏈接模式下訪問數據庫式,客戶端和數據庫服務器之間一直保持連接,槍彈參數批量操作的時間較長,長時間連接將導致數據庫服務器長期被占用[9~11]。而無鏈接模式較鏈接模式較數據庫連接占用時間大大縮短,占用系統資源也相應減少,因為在此種模式下槍彈參數數據庫批量操作批量操作的對象主要是內存中的DataSet、DataTable及DataRow[],只需要在需要提交進行數據交互式時,才打開數據連接。并且SqlDataAdapter類的數據填充方法Fill()方法和數據庫更新Update()都是自動打開和關閉數據庫連接,十分便捷。綜上可知,使用無鏈接模式的SqlDataAdapter類的更適合開發可靠安全、功能全面、效率高的槍彈參數數據庫批量操作程序。較采用SqlCommand命令類,采用SqlData-Adapter數據適配器類實現槍彈參數批量操作還具有代碼簡介、移植性好、易于實現模塊化等諸多優點,具體分析請見下文。
本文所研究的槍彈參數批量操作,采用批量操作數據表格的形式,以DataGridView數據顯示控件作為操作對象的載體。通過DataTable或DataSet作為中間層,SqlDataAdapter數據適配器類可實現DataSet或DataTable的與數據庫的雙向數據操作,設置DataGridView控件的DataSource屬性可實現DataSet類(或DataTable類)與DataGridView控件的雙向數據操作,進而可建立起DataGridView數據顯示控件與數據庫的雙向數據操作,即實現用戶對數據庫的批量操作,實現過程如圖1所示。各個具體槍彈參數數據庫批量操作功能模塊包括批量加載、批量管理、批量添加等的詳細介紹請見下文。

圖1 DataGridView與數據庫雙向操作
本文所述槍彈參數數據庫由兩個子數據庫,共11個數據表組成,數據庫的結構如圖2所示。

圖2 槍彈參數數據庫結構示意圖
將槍彈參數數據庫中的記錄批量加載到DataGridView數據顯示控件是對數據庫進行批量操作的前提。為減少窗口數量,采用一個DataGrid-View控件通過用戶選擇切換的方式顯示11個數據庫表。
通過SqlDataAdapter類將數據庫中的數據表批量加載到DataGridView控件的具體方法為
1)創建內存數據表DataTable或DataSet;
2)通過SqlDataAdapter適配器類的Fill()方法獲取數據庫中相應數據表填充到已創建的DataT-able或DataSet中;
3)設置DataGridView的DataSource屬性,確定已創建的DataTable或DataSet為DataGridView的當前數據源,DataGridView將同步顯示DataTable或DataSet中的數據表。
為方面代碼使用,將獲取數據表到DataTable的代碼封裝成下面的“FillDt”類如下。
class FillDt
{
SqlConnection myConnection;
DataTable myDataTable;
SqlDataAdapter myAdapter;
public DataTable GetDataTable(string ConStr,string SelectStr,)
{
myConnection=new SqlConnection(ConStr);
myAdapter=new SqlDataAdapter(SelectStr,myConnection);
myDataTable=new DataTable();
myAdapter.Fill(myDataTable);
return myDataTable;
}
}
為避免用戶誤操作,在用戶選擇批量功能之前,建議將批量加載后的DataGridView控件設置為不可編輯狀態。槍彈參數數據庫有幾百個字段名,采用SqlDataAdapter適配器類不僅可以批量獲取數據庫中的記錄,還可以獲取其字段名,省卻了人工設置DataGridView字段名的繁雜工作。
批量管理主要包括用戶對槍彈參數數據庫中的數據表的已有記錄進行批量刪除、批量修改及更新等操作[12]。三種批量管理的原理類似,通過Sql-DataTable適配器類的Update()方法將用戶的編輯更新到數據庫中。數據庫記錄批量加載后,用戶對DataGridView控件中的記錄進行編輯,DataGrid-View控件的數據源DataTable中自動進行同樣的編輯。批量管理的具體方法為
1)將DataGridView的數據記錄賦予DataTable或DataSet中,如已創建DataTable或DataSet并作為DataGridView數據源可忽略;
2)用戶對DataGridView的記錄修改、刪除、更新,與之綁定的DataSet或DataTable的數據記錄作相應修改、刪除、更新;
3)創建SqlDataAdapter對象,同時為它指定數據庫連接字符串、查詢命令等基本參數。數據庫連接字符串用來連接要操作的數據庫,查詢命令指定操作的數據庫中的具體數據表;
4)創建SQL命令創建器對象SqlCommand-Builder,SqlCommandBuilder對象用來自動產生刪除、修改、添加命令;
5)通過SqlDataAdapter類的 Update(DataTable)方法或Update(DataSet)方法將本地數據記錄Data-Set或DataTable的修改提交到數據庫服務器,完成數據庫端相應操作。
在處于不同的批量管理功能時,DataGridView控件的編輯屬性設置如表1所示。

表1 DataGridView控件批量操作屬性
以“彈頭參數”數據表為例,給出數據表批量管理的核心代碼如下:
DataTable dt=dataGridView1.DataSource as DataTable;
//將編輯后DataGridView復制到DataTable中,如已創建DataTable并作為DataGridView數據源可忽略。
String MyConnection='';
//設置數據庫連接字符串。
SqlDataAdapter da=new SqlDataAdapter('select*from彈頭參數',MyConnection);
//創建SqlDataAdapter適配器。
SqlCommandBuilder sqb=new SqlCommandBuilder(da);
//創建SqlComandBuilder命令創建器對象
da.Update(dt);
//將編輯后DataGridView的記錄更新到數據庫.
dt.AcceptChanges();
//Datatable進行初始化
需注意的是,使用SqlDataAdapter適配器類更新數據庫時,SelectCommand命令所查詢的數據表須指定主鍵,SqlComandBuilder類才能根據DataTabble的RowState屬性自動生成相應的SQL命令。更改提交后,需對Datatable進行初始化,以防止對下一次操作產生干擾。
批量管理采用三層結構,以內存數據表Datatable或DataSet作為中間層,并作為DataGridView的數據源,DataTable可以自動同步DataGridView的更改,可靈活設置各種數據管理功能,并且用戶不直接操作數據庫,而是操作儲存在內存中的數據庫的備份,操作完成后再將更改向數據庫服務器進行提交,比采用SqlCoommand命令直接操作數據庫更有利與保證數據庫數據的穩定、安全。SqlCoommand命令類適合修改簡單的數據庫記錄,以修改用戶密碼功能為例,基于SqlCommand類代碼如下所示。
string sqlstr='update CommonUser';
mycommand.CommandText=sqlstr+'set Password=@Pwd where ID=@ID';
SqlParameter id=new SqlParameter('@ID',SqlDbType.NVarChar,-1);
SqlParameter pwd=new SqlParameter('@pwd',SqlDb-Type.NVarChar,-1);
mycommand.Parameters.Add(pwd);
mycommand.Parameters.Add(id);
id.Value=txtID.Text.Trim();
pwd.Value=txtPwd.Text.Trim();
如上面代碼所示,SqlCoommand類的修改命令需要將字段名作為參數添加進去,還要對參數進行賦值。對于字段名較多的槍彈參數數據庫,這種代碼較為繁瑣,每個數據表都需重新寫代碼,移植性也較差。
批量添加時,只需要加載數據表的字段名,不需要加載記錄,可使用DataTable.Rows.Clear()方法刪除DataTable中的數據庫已有記錄,并保留字段名,被刪除的記錄RowState屬性為Detached,更新到數據庫中時,不會對已有記錄產生影響。也可以采用偽指令的方法,在SqlDataAdapter對象的SelectCommand查詢指令,設置查詢為空的指令,比如“select*from彈頭參數where 1=2”,這樣Fill()方法填充的DataTable只有列信息沒有行信息。如果采用Delete方法刪除,被刪除的記錄RowState屬性為Deteleted,只是被標記為刪除狀態,并沒有被真正刪除,更新時數據庫中的相應記錄會被刪除。
在用戶完成記錄添加后,需對用戶新添加的記錄進行檢驗,保證記錄含有主鍵且不重復。可復制已填充記錄的DataTable作為副本以用來查重。經檢驗合格后的記錄方可提交。SqlAdapter類的Update(DataRow[])方法可將指定的數據記錄數組提交到數據庫。如果DataRow[]中記錄的RowState屬性為Added,提交數據庫更新時將自動生成Insert命令將此記錄插入數據庫。
批量添加基于此原理,流程圖如圖3所示。
使用SqlDataAdapter類向數據庫批量添加記錄的核心代碼如下。
DataTable dt=dataGridView1.DataSource as DataTable;
//將編輯后DataGridView復制到DataTable中,如已創建DataTable并作為DataGridView數據源可忽略。
DataRow[]Rows=dt.Select();
//將 Datatable轉換為DataRow[]。
String MyConnection='';
//設置數據庫連接字符串。
SqlDataAdapter da=new SqlDataAdapter('select*from彈頭參數',MyConnection);
//創建SqlDataAdapter適配器。
SqlCommandBuilder scb=new SqlCommandBuilder(da1);
//創建SQL命令創建器對象SqlCommandBuilder,
da.Update(rows);
//通過SqlDataAdapter的Update(DataRow[])方法將新添加記錄插入數據庫。
dt.Clear();
Rows.Clear();
新添加的記錄也可從DataGridView控件中直接獲取,這時要用到微軟提供的唯一的DataGrid-ViewRow轉換DataRow方法:DataGridViewRow.DataBoundItem as DataRowView).Row。對數據庫插入的SQL命令包含多個參數,需要根據數據表的字段名和記錄各列值創建SqlParameter對象,并通過Add()或foreach關鍵字遍歷SqlCommand.Parameters添加參數,而槍彈參數數據庫中的數據表中的字段名名多達數百個,本槍彈參數數據庫批量添加操作的實現基于SqlDataAdapter對象的Update(DataRow[])方法,不需要人工代碼設置大量的SqlParameter參數對象,程序簡潔,移植性強,運行效率高,大大提高了程序開發效率。
為進一步減少窗口數量,本操作系統通過TreeView控件節點的選擇進行切換數據表。Tree-View控件清楚明了地展現數據庫的結構,切換不同的數據表也十分方便。
在一個操作界面,實現11個數據庫表的批量加載、批量添加、批量刪除、批量更新等多種功能,需合理設置各個功能選項及按鈕的邏輯關系,才能保證實現預期目標且不造成數據混亂。設計好的批量操作界面如圖4所示。

圖4 批量操作界面
本文基于槍彈參數數據庫的特點,采用Sql-DataAdapter類完成了數據庫的批量操作程序設計,用戶可在一個操作界面完成多個槍彈參數數據庫表的多種批量操作,代碼簡潔,移植性好,并且直接從數據庫自動讀取和更新,不需人工設置DataGridView控件和SqlCommand參數。本文按照程序進行模塊化設計,詳細地介紹了SqlAdapter類批量操作的相關方法、類及其原理,并與SqlCommand命令類實現批量數據庫操作作了較為詳細的對比,說明了SqlCommand命令類在實現批量操作時的局限性。本文還對程序開發過程中總結的重要的經驗和技術細節進行了介紹,可為開發人員提供一定的參考。