摘要:本文介绍使用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控件中显示来自两个表的信息
新闻热点
疑难解答
图片精选