摘要:本文介紹使用asp.net開發一個軟件公司內部員工業績評測系統,包括后臺所有員工信息管理,部門信息管理,所有部門評測細則信息管理;前臺員工每月自我評測和主管對員工的評測.重點介紹數據庫設計,以及重要web服務端和頁面控件的使用.筆者相信本文會對讀者的數據庫設計和使用asp.net開發頁面技術有很好的啟發和幫助。
一、 系統體系結構
visual studio .net 是微軟公司迄今為止推出的最強大的,完整的開發工具,用于生成 asp web 應用程序、xml web services、桌面應用程序和移動應用程序。asp.net 是一個已編譯的、基于.net 的環境.。下面的圖表給我們演示了visual studio.net framework是如何支持asp.net應用的。
visual c#(發音為 c sharp)是一種新的面向對象的編程語言,它從 c 和 c++ 演變而來,為開發應用程序提供了一種簡單和類型安全的語言。因此在編程環境及語言的選擇中,我們使用了asp.net構架來為頁面開發提供支持,visual c#來進行實際編程。我們的評測系統中采用的是傳統的三層體系結構,包括數據存儲層(sqlserver2000)、應用邏輯層(.aspx.cs),頁面顯示(.aspx)。
二、 數據庫設計
數據庫”ygpc”(員工評測)中共含有五個表,介紹如下:
1. employee,存放公司所有員工和主管基本信息。
2. department,所有部門基本信息.
3. bigrules ,包括評測細則大的分類情況,比如”遵守制度”, “專業技能”,”計劃與管理”,”工作成果”,”工作態度”等.
4. smallrules, 包括每個細則分類對應的具體評測細則,例如細則分類”專業技能”中對應的”熟練使用設計工具(如rational rose或visio等)”,” 熟練使用數據庫或其相關的應用如sql,olap等”,”熟悉公司的技術體系并能熟練地應用于開發當中”。
5. score, 每月評測結果分數,分為員工自測和主管對員工評測,針對每條評測細則存放每個員工每月相應的分數.
各個表主要字段和表間關系如下圖所示:
表名主要字段主鍵和外鍵employeeemployid,departid,leaderid,reallname, username,userpass, emal, telephone…….主鍵: employid
外鍵: departiddepartmentdepartid,leaderid,dname,ddescription…主鍵: departidsmallrulessmallid,bigid,departid simplediscription,fulldescription,score,主鍵: smallid
外鍵: bigid, departidbigrulesbigid,content,totalscore主鍵: bigidscoretestpersonid, testedpersonid,smallid, score, month 主鍵: 無
外鍵: smallid
在大多數的軟件公司中,部門分為研發,測試,客服等, 雇員分屬若干部門;各個部門既有相同又有不同的評測標準。比如在筆者所在的開發超市軟件的公司中,在遵守制度上各個部門需要相同的評測標準,例如:無遲到早退,有事向公司請假,無無故曠工等;同時各個部門又有不同的評測標準,比如在專業技能上,研發部門的員工需要掌握熟練的.net開發windows頁面技術;而客服部門需要掌握熟練的數據庫技術,隨時為各個店鋪查找商品銷售情況,商品進銷存情況等;在工作成果上,測試部門會有”測試漏測率”評測標準,而研發和客服部門就不需要。因此,在smallrules(評測細則)表中,不僅需要相應的bigrules(細則分類)中的bigid,使得”熟練使用開發兩種以上工具”對應著”專業技能”分類,同時還要存儲該細則所屬的部門id。
另外,在score表中,需要按照每月,每個評測人,每個被測人,每個評測細則分別存儲相應的細則上的得分,這樣無論是取自測成績還是主管對自己的評測成績都是十分方便的。其中所有id,分數, 分值,月份等數值型數據為int型,描述型信息都為varchar型。
三、 應用邏輯實現
1、應用概述
系統管理員,各個部門主管及員工從同樣的登陸頁面分別進入前后臺系統。系統管理員完成后臺員工信息管理,部門信息管理,各個部門評測標準信息管理等。前臺用戶包括各部門主管和普通員工。部門主管進入評測主頁面后,可以選擇本部門的任一員工,選擇工作當月為其打分;普通員工只能給自己當月評測。員工在主管為自己本月工作情況評測前可多次修改自己以前的評測結果,一旦主管為自己評測過就無法修改了;主管只有在員工評測之后才能為其打分,主管可為員工多次評定。
2、重要服務器和頁面控件的使用
我們使用了相當多的基本控件,比如button,textbox,htmlselect,dropdownlist,隱藏控件等。由于篇幅有限,現只介紹其中起到關鍵作用的控件。
(1) htmltable控件
。
該頁面在實現中的邏輯并不復雜,我們以文字敘述如下:遍歷bigrules表中每條評測分類,根據當前細則分類id從smallrules取出對應的若干條評測細則,同時判斷當前員工當月是否已經有過成績,如果有,則取出,放入”黃色”方框中,便于參考。進入該頁面后,還需要判斷是”誰”在給”誰”評測,如果是主管或者員工的自測,則將評測結果存入數據庫時
testpersonid,testedpersonid都填入同一id,否則testpersonid存放主管id,testedpersonid存放被測人id.
該頁面主要使用了htmltable控件。使用 htmltable控件對 html <table> 元素進行編程。在后臺頁面ide設計環境中,該控件不含任何內容。在從數據庫中取出數據后,我們可以體會到該控件的強大功能。htmltable控件由一個表table的 rows 集合中存儲的行(由 htmltablerow 對象表示)組成。每行均由存儲在行的 cells 集合中的單元格(由 htmltablecell 對象表示)組成。在實際編程中,首先需要填充若干個htmltablecell內容,一次加入到htmltablerow對象中,再將該htmltablerow對象加入到htmltable對象中。
(2) datagrid
datagrid控件與htmltable控件不同在于datagrid控件是web服務器端控件。以html語言書寫和以服務器端控件的實現在思維方式上已經有了很大的不同,對于html語言而言,只是一種標識;而對服務器端html控件而言,卻已演變成為一段程序,一個對象。
它不僅可以方便,快捷的完成數據庫中數據的綁定顯示,還可以在設計時生成包含“編輯”、“更新”、“取消”按鈕的列、包含自定義按鈕的列以及模板列。在后臺管理頁面中我們使用了該控件的編輯數據功能,點擊每一小項的edit按鈕可以更新該項內容。點擊update 控件就可完成數據庫內容的更新。
另外,在其他情況下也可使用datagrid控件
從該控件在不同情況下的使用我們體會到該控件的強大功能。這也正是asp.net編程構架給用戶提供的切實利益。
四、結束語
筆者在一家開發超市軟件的公司進行畢業設計時為公司開發了這個員工評測中心。盡管由于時間短促,未能做出功能更多,更豐富的頁面,但是也確實體會到了asp.net的種種優勢。同樣在數據庫的設計和使用上也積累了一定的經驗,希望能對大家有一定的啟迪。相信使用該技術同樣可以為公司做出功能更加全面的辦公自動化產品。
(以下源代碼不排版)
源代碼編譯環境:安裝visual studio.net 7.0,sqlserver2000
源代碼1(前臺評測主頁面):
//建立數據庫連接,取出bigrules表數據放入ds中
sqlconnection conn = new sqlconnection(“server=localhost;uid=sa;pwd=;database=ygpc”;
sqlcommand comm. = new sqlcommand(“select * from bigrules”,conn);
sqldataadapter da = new sqldataadapter(comm);
dataset ds;
da.fill(ds,”bigrules”);
int ntotalbig = ds.tables[“bigrules”].rows.count;
int k = convert.toint32(ds.tables["bigrules"].rows[0]["bigid"].tostring());
for(int ibig=0;k<=convert.toint32(ds.tables["bigrules"].rows[ntotalbig-1]["bigid"].tostring());k=convert.toint32(ds.tables["bigrules"].rows[ibig]["id"].tostring()))
//ibig代表bigrules表中行值,k代表ibig行對應的id值
{
string commtext = "select * from smallrules where bigid="+k+"order by id";
sqlcommand commsmall = new sqlcommand(commtext,conn);
sqldataadapter dasmall = new sqldataadapter(commsmall);
if(ds1!=null) ds1.clear();
ds1 = new dataset();//每次循環都需要更新ds1中記錄的細則數據
dasmall.fill(ds1,"smallrules");
int ntotalrows = ds1.tables["smallrules"].rows.count;
int i=convert.toint32(ds1.tables["smallrules"].rows[0]["id"].tostring());
string str = "select * from score where
_testpersonid="+testid+"and testedpersonid="+testedid+"and month="+curmon+" and smallid="+i;
//判斷當前被測員工當月是否已有過成績,即檢查score表中是否有與testedid, testid,curmon相符
//的記錄,判斷結果為true或false存入hidtested隱藏控件中,
// 在顯示”黃框”以往成績時起到作用,略
for(int z=0;i<=convert.toint32(ds1.tables["smallrules"]
_.rows[ntotalrows-1][“id”].tostring());
i=convert.toint32(ds1.tables[“smallrules”].rows[z][“id”].tostring()))
//z代表smallrules中的行值,i代表z行的id值,需要找出i值對應的score表的"成績"值
{
htmltablerow tr = new htmltablerow();
array.setvalue(indexpagerow++,i);
//array為靜態數組,記錄每個i值在頁面上的對應行,
// 因為各項評測smallrules經過后臺不斷的增,刪,改,其id值與頁面上的行并不對應
for(int j=0;j<ds1.tables["smallrules"].columns.count;j++)
{
htmltablecell tc = new htmltablecell();
if(j==0)//當前范圍的零行零列
{
if(i == convert.toint32(ds1.tables["smallrules"].rows[0]["id"].tostring()))
{
//最左的細則分類列,注意從bigrules表中取數據
tc.innerhtml = s.tables["bigrules"].rows[ibig][j+1].tostring()+
_ds.tables["bigrules"].rows[ibig]["totalscore"].tostring()+"分";
}
tr.cells.add(tc);
}
else //不是最左列
{
if(j!=ds1.tables["smallrules"].columns.count-1)//判斷是否最右列
{
tc.innerhtml = ds1.tables["smallrules"].rows[z][j].tostring();
}
else
{
//最右的成績分值列
if(hidtested.value==”true”)
//最后一個cell列含兩個textbox列,顯示上次評測的成績
{
textbox box1= new textbox();
box1.width = 30;
//找出i值對應的score表中的成績放入ds2
box1.text = ds2.tables["score"].rows[0]["score"].tostring();
box1.readonly = true;
box1.backcolor = system.drawing.color.beige;
tc.controls.add(box1);
}
textbox box = new textbox();
if(hidtested.value == "false")
box.width = 60;
else
box.width = 30;
box.attributes["onblur"]="javascript:onchange("+ds1.tables[
"smallrules"].rows[z][j-1].tostring()+",this)";
//javascript控制用戶評測分數在該項分值之內,
//ds1.tables["smallrules"].rows[z][j-1].tostring()
//傳給onchange函數該項評測細則分值
}
tr.cells.add(tc);//將htmltablecell對象存入htmltablerow對象中
}
}
t.rows.add(tr);//一行數據完成,加入到htmltable的rows集合中
z++;
}//一個細則分類的所有評測細則完成
ibig++;
}//下一個細則分類,如由”遵守制度”到”專業技能”
其中嵌入的javascript語句的onchange()函數在html頁面中head部分實現如下:
<script language=”javascript”>
function onchange(maxvalue,obj)
{
//maxvalue為該項細則的分值,obj為該項得分,是object型
parseint(obj.value,10); parseint(maxvalue,10);
if(!isnan(obj.value)) //判斷是否自然數
if(obj.value>maxvalue) //值超過范圍
{
alert('值超過范圍') obj.focus();}
else {}
else //值非法
{
alert('值非法') obj.focus();}
</script>
源代碼2(評測結果頁面,以一個datagrid為例):
datatable table1 = ds.tables.add("score");//ds,ds1為兩個dataset型數據集
table1.columns.add("smallid",typeof(int));//細則id列
table1.columns.add("realname", typeof(string));//測評人姓名
table1.columns.add("score", typeof(int));//該項細則得分
string commtext = "select smallid,realname,score from score, employee where score.testpersonid="+testid+"and score.testedpersonid="+testedid+"and score.month="+curmon+"order by score.smallid";
//其中testid,testedid為頁面進入時從前一頁面記錄的測評人id和被評人id值
sqlconnection conn = new sqlconnection(“server=localhost;uid=sa;pwd=;database=ygpc”;
conn.open();
sqlcommand comm= new sqlcommand(commtext,conn);
sqldatareader reader = com1.executereader();
int ncolcount= table1.columns.count;
while(reader.read())
{
system.data.datarow row = table1.newrow();
for(int i=0;i<ncolcount;i++)
{
row[i]=reader[i];
}
table1.rows.add(row);
}
datagrid1.datasource=ds.tables["score"].defaultview;
datagrid1.datamember =ds.tables["employee"].tablename;
datagrid1.databind();
//使用datasource和datamember就能在一個datagrid控件中顯示來自兩個表的信息
新聞熱點
疑難解答
圖片精選