房澤臣 陳川琳 蔡紅明 吳志林
(南京理工大學(xué)機械工程學(xué)院 南京 210094)
槍彈參數(shù)數(shù)據(jù)庫管理是槍彈一體化設(shè)計與分析系統(tǒng)的基礎(chǔ)功能之一,為槍彈的設(shè)計、分析提供支撐。該系統(tǒng)基于.NET FrameWork平臺,采用C#語言編寫程序,并采用SQL Server 2012數(shù)據(jù)庫。其中,槍彈參數(shù)數(shù)據(jù)庫管理的核心程序為批量操作程序。
批量操作程序的設(shè)計目的是方便用戶高效地管理、維護各個槍彈參數(shù)子數(shù)據(jù)庫,是數(shù)據(jù)庫管理系統(tǒng)的核心功能。大部分文獻(xiàn)采取SqlCommand對象對數(shù)據(jù)庫進(jìn)行添加和修改操作,但使用SqlCommand對象需針對不同的數(shù)據(jù)表編寫相應(yīng)的CommnadText,并且SqlCommand對象中參數(shù)要與數(shù)據(jù)表中的字段名一一對應(yīng),如果字段名較多,需人工添加參數(shù)[1]。
本文所述槍彈參數(shù)數(shù)據(jù)庫含11個數(shù)據(jù)庫表,數(shù)百個字段名,如果采用SqlCommand對象逐條操作記錄的方式,不僅使用人員的工作效率較低,而且開發(fā)人員也需投入較大精力開發(fā)大量的界面和繁瑣冗長的代碼。本研究基于上述兩點原因,采用SqlDataAdapter適配器類進(jìn)行設(shè)計,旨在提供代碼簡潔、移植性好、運行穩(wěn)定、使用方便的槍彈參數(shù)數(shù)據(jù)庫批量操作程序。
SqlDataAdapter數(shù)據(jù)適配器類是.NET Framework Data Provider for SQL Server數(shù)據(jù)提供程序中的核心類之一[2]。SqlDataAdapter適配器類可使用SQL Sever中的數(shù)據(jù)填充到內(nèi)存數(shù)據(jù)集DataSet或內(nèi)存數(shù)據(jù)表 DataTable,并根據(jù) DataSet、DataTable及DataRow[]中的RowState屬性的更改自動生成相應(yīng)SQL命令更新SQL Sever數(shù)據(jù)庫。
ADO.NET提供鏈接模式和無鏈接模式兩種數(shù)據(jù)庫訪問模式[3~6]。鏈接模式主要依靠 SqlCommand命令類實現(xiàn)數(shù)據(jù)庫操作,無鏈接模式主要依靠SqlDataAdapter數(shù)據(jù)適配器類實現(xiàn)數(shù)據(jù)庫操作。SqlCommand對象直接向數(shù)據(jù)庫服務(wù)器發(fā)送SQL命令實時操作數(shù)據(jù)庫,數(shù)據(jù)處理邏輯通常時間較短,不利于實現(xiàn)復(fù)雜的處理邏輯[7~8]。SqlDataAdapter數(shù)據(jù)適配器類,操作對象為DataSet、DataTable及DataRow[],在提交之前可像操作數(shù)據(jù)庫那樣對DataSet、DataTable及DataRow[]中的數(shù)據(jù)記錄進(jìn)行修改、驗證、取消等操作,當(dāng)數(shù)據(jù)記錄符合用戶要求后再進(jìn)行提交,更容易實現(xiàn)邏輯復(fù)雜、數(shù)據(jù)安全的數(shù)據(jù)庫操作。
在鏈接模式下訪問數(shù)據(jù)庫式,客戶端和數(shù)據(jù)庫服務(wù)器之間一直保持連接,槍彈參數(shù)批量操作的時間較長,長時間連接將導(dǎo)致數(shù)據(jù)庫服務(wù)器長期被占用[9~11]。而無鏈接模式較鏈接模式較數(shù)據(jù)庫連接占用時間大大縮短,占用系統(tǒng)資源也相應(yīng)減少,因為在此種模式下槍彈參數(shù)數(shù)據(jù)庫批量操作批量操作的對象主要是內(nèi)存中的DataSet、DataTable及DataRow[],只需要在需要提交進(jìn)行數(shù)據(jù)交互式時,才打開數(shù)據(jù)連接。并且SqlDataAdapter類的數(shù)據(jù)填充方法Fill()方法和數(shù)據(jù)庫更新Update()都是自動打開和關(guān)閉數(shù)據(jù)庫連接,十分便捷。綜上可知,使用無鏈接模式的SqlDataAdapter類的更適合開發(fā)可靠安全、功能全面、效率高的槍彈參數(shù)數(shù)據(jù)庫批量操作程序。較采用SqlCommand命令類,采用SqlData-Adapter數(shù)據(jù)適配器類實現(xiàn)槍彈參數(shù)批量操作還具有代碼簡介、移植性好、易于實現(xiàn)模塊化等諸多優(yōu)點,具體分析請見下文。
本文所研究的槍彈參數(shù)批量操作,采用批量操作數(shù)據(jù)表格的形式,以DataGridView數(shù)據(jù)顯示控件作為操作對象的載體。通過DataTable或DataSet作為中間層,SqlDataAdapter數(shù)據(jù)適配器類可實現(xiàn)DataSet或DataTable的與數(shù)據(jù)庫的雙向數(shù)據(jù)操作,設(shè)置DataGridView控件的DataSource屬性可實現(xiàn)DataSet類(或DataTable類)與DataGridView控件的雙向數(shù)據(jù)操作,進(jìn)而可建立起DataGridView數(shù)據(jù)顯示控件與數(shù)據(jù)庫的雙向數(shù)據(jù)操作,即實現(xiàn)用戶對數(shù)據(jù)庫的批量操作,實現(xiàn)過程如圖1所示。各個具體槍彈參數(shù)數(shù)據(jù)庫批量操作功能模塊包括批量加載、批量管理、批量添加等的詳細(xì)介紹請見下文。
圖1 DataGridView與數(shù)據(jù)庫雙向操作
本文所述槍彈參數(shù)數(shù)據(jù)庫由兩個子數(shù)據(jù)庫,共11個數(shù)據(jù)表組成,數(shù)據(jù)庫的結(jié)構(gòu)如圖2所示。
圖2 槍彈參數(shù)數(shù)據(jù)庫結(jié)構(gòu)示意圖
將槍彈參數(shù)數(shù)據(jù)庫中的記錄批量加載到DataGridView數(shù)據(jù)顯示控件是對數(shù)據(jù)庫進(jìn)行批量操作的前提。為減少窗口數(shù)量,采用一個DataGrid-View控件通過用戶選擇切換的方式顯示11個數(shù)據(jù)庫表。
通過SqlDataAdapter類將數(shù)據(jù)庫中的數(shù)據(jù)表批量加載到DataGridView控件的具體方法為
1)創(chuàng)建內(nèi)存數(shù)據(jù)表DataTable或DataSet;
2)通過SqlDataAdapter適配器類的Fill()方法獲取數(shù)據(jù)庫中相應(yīng)數(shù)據(jù)表填充到已創(chuàng)建的DataT-able或DataSet中;
3)設(shè)置DataGridView的DataSource屬性,確定已創(chuàng)建的DataTable或DataSet為DataGridView的當(dāng)前數(shù)據(jù)源,DataGridView將同步顯示DataTable或DataSet中的數(shù)據(jù)表。
為方面代碼使用,將獲取數(shù)據(jù)表到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控件設(shè)置為不可編輯狀態(tài)。槍彈參數(shù)數(shù)據(jù)庫有幾百個字段名,采用SqlDataAdapter適配器類不僅可以批量獲取數(shù)據(jù)庫中的記錄,還可以獲取其字段名,省卻了人工設(shè)置DataGridView字段名的繁雜工作。
批量管理主要包括用戶對槍彈參數(shù)數(shù)據(jù)庫中的數(shù)據(jù)表的已有記錄進(jìn)行批量刪除、批量修改及更新等操作[12]。三種批量管理的原理類似,通過Sql-DataTable適配器類的Update()方法將用戶的編輯更新到數(shù)據(jù)庫中。數(shù)據(jù)庫記錄批量加載后,用戶對DataGridView控件中的記錄進(jìn)行編輯,DataGrid-View控件的數(shù)據(jù)源DataTable中自動進(jìn)行同樣的編輯。批量管理的具體方法為
1)將DataGridView的數(shù)據(jù)記錄賦予DataTable或DataSet中,如已創(chuàng)建DataTable或DataSet并作為DataGridView數(shù)據(jù)源可忽略;
2)用戶對DataGridView的記錄修改、刪除、更新,與之綁定的DataSet或DataTable的數(shù)據(jù)記錄作相應(yīng)修改、刪除、更新;
3)創(chuàng)建SqlDataAdapter對象,同時為它指定數(shù)據(jù)庫連接字符串、查詢命令等基本參數(shù)。數(shù)據(jù)庫連接字符串用來連接要操作的數(shù)據(jù)庫,查詢命令指定操作的數(shù)據(jù)庫中的具體數(shù)據(jù)表;
4)創(chuàng)建SQL命令創(chuàng)建器對象SqlCommand-Builder,SqlCommandBuilder對象用來自動產(chǎn)生刪除、修改、添加命令;
5)通過SqlDataAdapter類的 Update(DataTable)方法或Update(DataSet)方法將本地數(shù)據(jù)記錄Data-Set或DataTable的修改提交到數(shù)據(jù)庫服務(wù)器,完成數(shù)據(jù)庫端相應(yīng)操作。
在處于不同的批量管理功能時,DataGridView控件的編輯屬性設(shè)置如表1所示。
表1 DataGridView控件批量操作屬性
以“彈頭參數(shù)”數(shù)據(jù)表為例,給出數(shù)據(jù)表批量管理的核心代碼如下:
DataTable dt=dataGridView1.DataSource as DataTable;
//將編輯后DataGridView復(fù)制到DataTable中,如已創(chuàng)建DataTable并作為DataGridView數(shù)據(jù)源可忽略。
String MyConnection='';
//設(shè)置數(shù)據(jù)庫連接字符串。
SqlDataAdapter da=new SqlDataAdapter('select*from彈頭參數(shù)',MyConnection);
//創(chuàng)建SqlDataAdapter適配器。
SqlCommandBuilder sqb=new SqlCommandBuilder(da);
//創(chuàng)建SqlComandBuilder命令創(chuàng)建器對象
da.Update(dt);
//將編輯后DataGridView的記錄更新到數(shù)據(jù)庫.
dt.AcceptChanges();
//Datatable進(jìn)行初始化
需注意的是,使用SqlDataAdapter適配器類更新數(shù)據(jù)庫時,SelectCommand命令所查詢的數(shù)據(jù)表須指定主鍵,SqlComandBuilder類才能根據(jù)DataTabble的RowState屬性自動生成相應(yīng)的SQL命令。更改提交后,需對Datatable進(jìn)行初始化,以防止對下一次操作產(chǎn)生干擾。
批量管理采用三層結(jié)構(gòu),以內(nèi)存數(shù)據(jù)表Datatable或DataSet作為中間層,并作為DataGridView的數(shù)據(jù)源,DataTable可以自動同步DataGridView的更改,可靈活設(shè)置各種數(shù)據(jù)管理功能,并且用戶不直接操作數(shù)據(jù)庫,而是操作儲存在內(nèi)存中的數(shù)據(jù)庫的備份,操作完成后再將更改向數(shù)據(jù)庫服務(wù)器進(jìn)行提交,比采用SqlCoommand命令直接操作數(shù)據(jù)庫更有利與保證數(shù)據(jù)庫數(shù)據(jù)的穩(wěn)定、安全。SqlCoommand命令類適合修改簡單的數(shù)據(jù)庫記錄,以修改用戶密碼功能為例,基于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類的修改命令需要將字段名作為參數(shù)添加進(jìn)去,還要對參數(shù)進(jìn)行賦值。對于字段名較多的槍彈參數(shù)數(shù)據(jù)庫,這種代碼較為繁瑣,每個數(shù)據(jù)表都需重新寫代碼,移植性也較差。
批量添加時,只需要加載數(shù)據(jù)表的字段名,不需要加載記錄,可使用DataTable.Rows.Clear()方法刪除DataTable中的數(shù)據(jù)庫已有記錄,并保留字段名,被刪除的記錄RowState屬性為Detached,更新到數(shù)據(jù)庫中時,不會對已有記錄產(chǎn)生影響。也可以采用偽指令的方法,在SqlDataAdapter對象的SelectCommand查詢指令,設(shè)置查詢?yōu)榭盏闹噶?,比如“select*from彈頭參數(shù)where 1=2”,這樣Fill()方法填充的DataTable只有列信息沒有行信息。如果采用Delete方法刪除,被刪除的記錄RowState屬性為Deteleted,只是被標(biāo)記為刪除狀態(tài),并沒有被真正刪除,更新時數(shù)據(jù)庫中的相應(yīng)記錄會被刪除。
在用戶完成記錄添加后,需對用戶新添加的記錄進(jìn)行檢驗,保證記錄含有主鍵且不重復(fù)??蓮?fù)制已填充記錄的DataTable作為副本以用來查重。經(jīng)檢驗合格后的記錄方可提交。SqlAdapter類的Update(DataRow[])方法可將指定的數(shù)據(jù)記錄數(shù)組提交到數(shù)據(jù)庫。如果DataRow[]中記錄的RowState屬性為Added,提交數(shù)據(jù)庫更新時將自動生成Insert命令將此記錄插入數(shù)據(jù)庫。
批量添加基于此原理,流程圖如圖3所示。
使用SqlDataAdapter類向數(shù)據(jù)庫批量添加記錄的核心代碼如下。
DataTable dt=dataGridView1.DataSource as DataTable;
//將編輯后DataGridView復(fù)制到DataTable中,如已創(chuàng)建DataTable并作為DataGridView數(shù)據(jù)源可忽略。
DataRow[]Rows=dt.Select();
//將 Datatable轉(zhuǎn)換為DataRow[]。
String MyConnection='';
//設(shè)置數(shù)據(jù)庫連接字符串。
SqlDataAdapter da=new SqlDataAdapter('select*from彈頭參數(shù)',MyConnection);
//創(chuàng)建SqlDataAdapter適配器。
SqlCommandBuilder scb=new SqlCommandBuilder(da1);
//創(chuàng)建SQL命令創(chuàng)建器對象SqlCommandBuilder,
da.Update(rows);
//通過SqlDataAdapter的Update(DataRow[])方法將新添加記錄插入數(shù)據(jù)庫。
dt.Clear();
Rows.Clear();
新添加的記錄也可從DataGridView控件中直接獲取,這時要用到微軟提供的唯一的DataGrid-ViewRow轉(zhuǎn)換DataRow方法:DataGridViewRow.DataBoundItem as DataRowView).Row。對數(shù)據(jù)庫插入的SQL命令包含多個參數(shù),需要根據(jù)數(shù)據(jù)表的字段名和記錄各列值創(chuàng)建SqlParameter對象,并通過Add()或foreach關(guān)鍵字遍歷SqlCommand.Parameters添加參數(shù),而槍彈參數(shù)數(shù)據(jù)庫中的數(shù)據(jù)表中的字段名名多達(dá)數(shù)百個,本槍彈參數(shù)數(shù)據(jù)庫批量添加操作的實現(xiàn)基于SqlDataAdapter對象的Update(DataRow[])方法,不需要人工代碼設(shè)置大量的SqlParameter參數(shù)對象,程序簡潔,移植性強,運行效率高,大大提高了程序開發(fā)效率。
為進(jìn)一步減少窗口數(shù)量,本操作系統(tǒng)通過TreeView控件節(jié)點的選擇進(jìn)行切換數(shù)據(jù)表。Tree-View控件清楚明了地展現(xiàn)數(shù)據(jù)庫的結(jié)構(gòu),切換不同的數(shù)據(jù)表也十分方便。
在一個操作界面,實現(xiàn)11個數(shù)據(jù)庫表的批量加載、批量添加、批量刪除、批量更新等多種功能,需合理設(shè)置各個功能選項及按鈕的邏輯關(guān)系,才能保證實現(xiàn)預(yù)期目標(biāo)且不造成數(shù)據(jù)混亂。設(shè)計好的批量操作界面如圖4所示。
圖4 批量操作界面
本文基于槍彈參數(shù)數(shù)據(jù)庫的特點,采用Sql-DataAdapter類完成了數(shù)據(jù)庫的批量操作程序設(shè)計,用戶可在一個操作界面完成多個槍彈參數(shù)數(shù)據(jù)庫表的多種批量操作,代碼簡潔,移植性好,并且直接從數(shù)據(jù)庫自動讀取和更新,不需人工設(shè)置DataGridView控件和SqlCommand參數(shù)。本文按照程序進(jìn)行模塊化設(shè)計,詳細(xì)地介紹了SqlAdapter類批量操作的相關(guān)方法、類及其原理,并與SqlCommand命令類實現(xiàn)批量數(shù)據(jù)庫操作作了較為詳細(xì)的對比,說明了SqlCommand命令類在實現(xiàn)批量操作時的局限性。本文還對程序開發(fā)過程中總結(jié)的重要的經(jīng)驗和技術(shù)細(xì)節(jié)進(jìn)行了介紹,可為開發(fā)人員提供一定的參考。