调研后发现近三年机试都是数据库+C#做一个小型管理系统。在这里边复习边做笔记。
拿15的作为练手材料。
首先是建立数据库
注意将数据库的文件跟日志的路径放到考试要求的文件夹下。
然后点击右上角的新建查询来建表。建议有约束的表格用SQL语言来建速度较快。
员工关系表EMPLOYEE(员工号EmpNo,员工姓名EmpName,性别EmpSex,年龄EmpAge)
示例:E01, 张三,男, 20
工作关系表WORKS(EmpNo员工号,CmpNo公司号,Salary薪水)
示例:E01,C01,2000
公司关系表COMPANY(CmpNo公司号,CmpName公司名)
示例:C01,阳关科技
通过近三年的题目发现。一般都是建立3个表,中间的表有两个外键是来自于第1, 3两个表的,所以建表前看清楚,先建两个独立的表。
CREATE TABLE EMPLOYEE(
EmpNo varchar(10) primary key,
EmpName nvarchar(20) not null,
EmpSex nvarchar(10) check(EmpSex='男' or EmpSex='女'),
EmpAge int check(EmpAge>0));
注意
第三个表COMPANY
create table COMPANY(
CmpNo varchar(10) primary key,
CmpName nvarchar(20) not null);
第二个表WORKS
CREATE TABLE WORKS(
CmpNo varchar(10),
EmpNo varchar(10),
Salary int check(Salary>0),
PRIMARY KEY(EmpNo, CmpNo),
foreign key (EmpNo) references EMPLOYEE(EmpNo),
foreign key (CmpNo) references COMPANY(CmpNo));
实体完整性:必须满足的完整性之一,若一个属性是主属性,则不能为空。
参照完整性:必须满足的完整性之二,比如WORKS中引用了EMPLOYEE的EmpNo,则EmpNo必须是存在于EMPLOYEE中的。
之后便是插入数据,一定要使用语言。可能会要求将insert语句也保存下来。
右键表格,选编辑前200行。
之后备份。右击我们的数据库SCUT,任务,备份。记得修改路径到非C盘。填写文件名加后缀“bak”.
具体要求如下:
2.完成对员工关系表的添加,删除,修改和浏览四项功能。老师的性别要求用单选按钮实现。(15分)
3.统计和查询:
(1)根据员工号或员工名查找员工所在的公司名和工资,员工号或员工名不能文本输入,要求使用下拉菜单实现,并与数据库中现有信息一致(10分)
(2)统计年龄至少为40岁员工的总工资,工资按从大到小顺序排列;与数据库中现有信息一致(10分)
(3)查询至少具有两份工作员工的姓名和其公司名。(10分)
4.具有数据完整性校验功能,当出现数据异常和操作异常时,程序应给出清楚完整的异常提示信息。(10分)
先解决SQL查询问题。
首先解决的思路就是将所需要的信息的表连接在一起。使用外键相连。比如将EMPLOYEE& COMPANY相连,select * from EMPLOYEE,COMPANY where EMPLOYEE.EmpNo=COMPANY.CmpNo;
解:(1)表中需要员工号EmpNo,员工名EmpName,员工所在公司名CmpName和工资Salary。所以需要连接三个表。
select EMPLOYEE.EmpNo as '员工号',EMPLOYEE.EmpName as '员工名',
COMPANY.CmpName as '公司名', Salary as '工资'
where EMPLOYEE.EmpNo=WORKS.EmpNo
and COMPANY.CmpNo=WORKS.CmpNo;
(2)
查询条件1:40岁以上员工
查询条件2:总工资
查询条件3:从大到小排列
select EMPLOYEE.EmpNo, EMPLOYEE.EmpName, EMPLOYEE.Empage, sum(WORKS.Salary) as salary
from EMPLOYEE, WORKS
where EMPLOYEE.EmpNo=WORKS.EmpNo
group by EMPLOYEE.EmpNo, EMPLOYEE.EmpName,EMPLOYEE.EmpAge
having EMPLOYEE.EmpAge>40
order by salary desc;
(3)至少有两份工作的员工及公司名
计算个数使用count。
select EMPLOYEE.EmpNo
from WORKS
group by EMPLOYEE.EmpNo
having count(EMPLOYEE.EmpNo)>=2;
我们需要这个表中的EmpNo来查找员工的名字,以及公司名。所以连接4个表。这里涉及到嵌套子查询。可以直接将上面代码作为一个独立的表格,比如查询这些有两份工作的员工名字
select EMPLOYEE.EmpName
from EMPLOYEE
where EMPLOYEE.EmpNo in (
select EMPLOYEE.EmpNo
from WORKS
group by EMPLOYEE.EmpNo
having count(EMPLOYEE.EmpNo)>=2);
所以连接四个表。则是
select EMPLOYEE.EmpName, COMPANY.CmpName
from EMPLOYEE, COMPANY, (
select EMPLOYEE.EmpNo
from WORKS
group by EMPLOYEE.EmpNo
having count(EMPLOYEE.EmpNo)>=2) as c1
where EMPLOYEE.EmpNo=c1.EmpNo
and EMPLOYEE.CmpNo=COMPANY.CmpNo;
之后是C#编程。
C#首先是拖控件,有点类似于Andriod。在vs中的视图中打开工具箱侧边栏。常用的控件用图中红框框出来了
先审题。题目要求不要把所有操作全部集中在一个菜单内。所以我们使用容器里的TabControl。将其拖到Form1的窗口中右键属性。在如图中的TabPage位置进入就可以添加,移除标签,并且修改标签中的字。根据题目有四个要求。1是一个显示当前数据库中的EMPLOYEE表格内容并且提供增删改功能,2,3,4分别是上面实现的查询。所以总有4个tab
之后每个标签下都使用ListView来显示查询结果。
首先是属性:这里只需要改几处,
View-details
代码:以上属性更改后点击一项同一行的都会被选中。
· 在修改时需要在两个窗口间传递数据,参考安卓的Intent,我们需要读取该行的数据放到Intent中。此时读取第一行的第一个数据的代码是(注意是数组从0开始)listView1.SelectedItems[0].SubItems[0].Text;
其中SelectedItems是一个数组,里面存放了你选择的ListView行。SubItems则是该行中的某一列。
· 在改与删时代码需要加入判断是否有选中的逻辑。所以此时代码是listView1.SelectedItems.Count>0
,否则会报错:未处理ArgumentOutOfRangeException
InvalidArgument=“0”的值对于“index”无效。
参数名: index
· 在显示查询到的数据时需要先加载表头才能够显示出来。代码是
//n是该行分成n等分,m是这个表头占m/n行的宽度
listView1.Columns.Add('表头名',listView1.Width/n-m',HorizontalAlignment.Left)
· 加载表头后要将数据一个个添加到行,行组成表。代码有通用性
//通过查表返回DataTable类型表格,数据由此表格得到,@表示禁止字符串强制转换。注意数据库语句最后要加‘;’
DataTable table=db.GetBySql(@"select * from EMPLOYEE;");
//与EndUpdate()配合有效提高加载速度,注意先建表头
listView1.BeginUpdate();
listView1.Columns.Add("员工编号", listView1.Width / 4 - 1, HorizontalAlignment.Left);
listView1.Columns.Add("员工姓名", listView1.Width / 4 - 1, HorizontalAlignment.Left);
listView1.Columns.Add("员工性别", listView1.Width / 4 - 1, HorizontalAlignment.Left);
listView1.Columns.Add("员工年龄", listView1.Width / 4 - 1, HorizontalAlignment.Left);
for(int i=0;i
ListViewItem listViewItem =new ListViewItem();//新建一行
for (int j = 0; j < table.Columns.Count; j++)
{
if (j <= 0)
{
listViewItem.Text = table.Rows[i][j] + ""; //第一列使用Text。后面才是SubItem
}
else
{
listViewItem.SubItems.Add(table.Rows[i][j] + "");
}
listView1.Items.Add(listViewItem);//添加该行
}
}
listView1.EndUpdate();
在判断数据有效性时需要遍历整个ListView,使用foreach遍历listView中的ListViewItem。与上面的相同,SubItems[i]表示这一行的第i-1列的内容。
foreach(ListViewItem item in this.listView1.Items){
if(Intent.dict['form2_textbox2_text"]+""==item.SubItems[0].Text){}
}
注意在添加行时,第一列是使用listViewItem.Text来设置的。之后则是使用listViewItem.SubItems.Add来添加。dataTable.Row[i][j]要加“”强制转换成字符串
删除选中行:listView1.SelectedItems[0].Remove();
combobox是下拉框。即题目要求的要求使用下拉菜单实现。属性只需要将DropDownStyle设置为DropDownList(不可编辑)。
将员工名/员工编号加载进comboBox
table=db.getBySql(@"select EmpNo from EMPLOYEE");
for(int i=0;i<table.Rows.Count;i++)
for(int j=0;j<table.Columns.Count;j++)
comboBox1.Items.Add(table.Rows[i][j]+"");
comboBox1.SelectedIndex=0;//设置显示为第1个
获取选中的comboBox:comboBox1.Text
在选中查询后,若想表格只显示当前的员工信息,则需要将listView清空,使用listView2.clear();
但使用后表头也会没有,所以需要注意每次clear后重新增加表头
与安卓类似。直接在设计界面选中按钮,然后在属性框中的闪电标志下的Click中填入Click事件函数的函数名,回车,就会自动生成函数
在Program.cs中可以设定应用程序入口点,默认新建项目时的窗口文件Form1.cs。
Form的属性设置FormBorderStyle为FixedSingle,MaximizeBox,MinimizeBox为false,即无法最大最小化。StartPosition为CenterScreen。事件中Load即弹出窗口时运行的函数。这个项目中有多个子菜单。几个查询都是点击标签即显示,所以在弹出窗口时就要查询好查好,放在Form1_Load()中。鼠标点击事件则按上面说的自动生成,在load函数外。
添加修改员工时需要弹出第二个窗口来填写信息,这时候直接新建一个对象Form2就好。Form2是个新的窗口Form2 form2=new Fomr2();
若要制造登陆窗口切换到另外一个窗口的效果,则使用
this.Hide();
form2.Show();
如果是非初始窗口则可以使用close。
与安卓一样使用Intent的概念。新建一个Intent静态类,这个类是个字典。这样就可以通过键值来存储信息,通过静态的来共享。
using System;
using System.Collections.Generic;
using System.Text;
namespace SCUT
{
class Intent
{
public static Dictionary<string, Object> dict=new Dictiionary<string, object>();
}
}
例子:
//存:
Intent.dict["form2_textbox1_text"]=textBox1.Text;
Intent.dict["form2_raidobutton"]="男";
//取:
listViewItem.SubItems.Add(Intent.dict["form2_textbox1_text"]+"");
db.getBySql(@"select EmpName From EMPLOYEE where EmpNo='"+Intent.dict["form2_textbox2_text"]+"';"
连接数据库语句时要特别该变量是字符串还是数字,如果是varchar则要加’ ‘,数字则不用。
使用DialogResult来判断是否正确返回
//form1.cs
if(form2.showDialog()==DialogResult.OK){}
//form2.cs
this.DialogResult=DialogReslut.OK;
this.close();
在最开始,先建立两个工具类,一个是数据库的操作,一个是Intent。这里说数据库:
首先是建立连接。写在构造函数中:
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;//DataTable用到
using System.Data.SqlClient;//一系列的数据库操作类用到
private SqlConnection sqlConnection;
public DB(){
sqlConnection=new SqlConnection(@"server=.\SQLEXPRESS;database=SCUT;Trusted_Connection=SSPI;");//server名字看数据库的
sqlConnection.Open();//要Open,否则无法增删
}
数据库的操作分为增删改和查两大类。因为前一类不会返回表,只执行操作,而查询需要返回的表。
所以分成两个函数;
public Datatable getSql(string sql){
SqlDataAdapter sqlDataAdapter=new SqlDataAdapter(new SqlCommand(sql, sqlConnection));
DataTable dataTable=new DataTable();
sqlDataAdapter.Fill(dataTable);
return dataTable;
}
public void setSql(string sql){
new SqlCommand(sql, sqlConnection).ExecuteNonQuery();
}
最后需要析构函数关闭数据库
public void Dispose(){
sqlConnection.Close();
}