一.實驗要求
掌握並運用ADO.NET技術,實現一個C/S版本的信息管理系統。
(1)設計一個學生成績管理信息系統,能對學生的成績記錄進行方便的輸入、查詢、修改等操作,以及綜合統計查詢等。
(2)對學生成績的綜合查詢,如查詢個人的單科或所有成績/不及格成績,查詢某門課程的所有程序等。
(3)參考示例文件DbDemo。
(4)至少實現對一個數據表的完整操作(CRUD,增刪查改)、綜合(複合條件)查詢。
(5)鼓勵使用分層方式完成實驗。
(6)正確理解和熟練運用ADO.NET 數據訪問模型,理解並練習運用數據庫相關理論:事務、關係/外鍵約束、存儲函數等。
二. 設計思路
本次實驗是要做一個基於數據庫的應用軟件,採用了表示層、業務邏輯層和數據訪問層的三層結構。由於之前做數據庫課程設計已經採用過C#和Linq完成,所以我使用Linq來操作數據,相對來說會比較熟悉,所以這次的實驗仍然採用Linq來完成——使用Linq讀取和操作數據,再綁定到控件上。
1.數據訪問層(代碼在Model文件夾內)
數據訪問層主要分爲兩個部分,一個部分是DBContext的建立,另外一部分是把每一個數據庫表建立爲一個個獨立的對象,並聲明裏面的屬性。
//建立DBContext
public System.Data.Linq.Table<Classes> Classes;//聲明班級表對象
public System.Data.Linq.Table<Courses> Courses; //聲明課程表對象
public System.Data.Linq.Table<Roles> Roles; //聲明角色表對象
public System.Data.Linq.Table<Sorces> Sorces; //聲明成績表對象
public System.Data.Linq.Table<Student> Student; //聲明學生表對象
public System.Data.Linq.Table<Users> Users; //聲明用戶表對象
public SchoolMgrDataSetDataContext():base(connectionString){} //數據庫上下文
//聲明對象表中的屬性以及數據類型,get、set操作,以班級表(Classes)爲例
[Key]//聲明ClassID爲主鍵
private int ClassID { get; set; };
[StringLength(4,ErrorMessage="請正確輸入4爲年份"),Required ]
private string Year { get; set; };
[StringLength(50,ErrorMessage="請正確專業"),Required ]
private string Major{ get; set; };
[Required(ErrorMessage="請輸入班號!")]
private int ClassNumber{ get; set; };
private EntitySet<Student> _Student;
2.邏輯業務層(代碼在Logic文件夾內)
該層主要是用於接收來時表示層的數據處理請求,包括對數據的增刪查改,以及數據庫中表與表之間的各種連接。
//增:以在成績表中增加一條成績記錄爲例
try
{
SchoolMgr.Model.SchoolMgrDataSetDataContext myDB =
new Model.SchoolMgrDataSetDataContext();
//建立數據庫上下文
var mySorce =
myDB.Sorces.Where(p => p.CourseID == CourseID && p.StudentID == StudentID);
//檢查準備插入的成績記錄是否已經在表中,以防重複插入
if (mySorce.Count() ==0)//如果成績表(Sorce)中沒有該數據則插入
{
var myNewSorce = new Model.Sorces();//新建一個成績表元組對象
myNewSorce.CourseID = CourseID;//課程ID
myNewSorce.StudentID = StudentID;//學號
myNewSorce.Sorce = SorceNumber;//成績
myDB.Sorces.InsertOnSubmit(myNewSorce);//在成績表插入該記錄
}
……
myDB.SubmitChanges();//提交插入,由於在數據庫中已經採用了Check的約束,
//如果成績不在0~100之間的範圍內,將會出現異常。
return true;//如果插入成功,就返回true,表示插入成功。
}
catch
{
return false;//插入失敗,返回false,表示插入失敗。
}
//刪:以刪除一條成績記錄爲例。
SchoolMgr.Model.SchoolMgrDataSetDataContext myDB =
new Model.SchoolMgrDataSetDataContext();
var mySorceLog = myDB.Sorces.First(p => p.SorceID == SorceID);
//查找出需要被刪除的元組
try
{
myDB.Sorces.DeleteOnSubmit(mySorceLog);//刪除該元組
myDB.SubmitChanges();//提交
return true;//如果刪除成功,則不會有異常出現,返回刪除成功
}
catch
{
return false; //如果刪除失敗,則會有出現異常,返回刪除失敗
}
//刪:以刪除成績表中某學號的所有成績記錄爲例,同時刪除多條記錄
SchoolMgr.Model.SchoolMgrDataSetDataContext myDB =
new Model.SchoolMgrDataSetDataContext();
IEnumerable<SchoolMgr.Model.Sorces> deleteSorceLog =
myDB.Sorces.Where(p => p.StudentID.Contains(StudentID));
//選擇出包含(Contain)StudentID的成績記錄
try
{
myDB.Sorces.DeleteAllOnSubmit(deleteSorceLog);//刪除枚舉隊列中的所有元組
myDB.SubmitChanges();//提交到數據庫
return true;
}
catch
{
return false;
}
//查:以顯示一張成績表爲例,根據學號,找出某名學生的所有課程的成績。
SchoolMgr.Model.SchoolMgrDataSetDataContext myDB =
new Model.SchoolMgrDataSetDataContext();
//以下是自然連接的Linq語句
IQueryable<SchoolMgr.Model.SorceTable> sorceTable =
from myClass in myDB.Classes
join myStudent in myDB.Student.Where(p => p.StudentID == StudentID)
on myClass.ClassID equals myStudent.ClassID
into myStudentClasses
from myStudentClass in myStudentClasses
//獲得該學生的學生信息:班級、姓名和學號
join mySorce in myDB.Sorces
on myStudentClass.StudentID equals mySorce.StudentID
into mySoceStudentClasses
//獲得該學生的成績信息:成績
from mySorceStudentClass in mySoceStudentClasses
join myCourse in myDB.Courses
on mySorceStudentClass.CourseID equals myCourse.CourseID
into myCourseSorceStudentClasses
//獲得該學生的課程信息:課程名稱
from myCourseSorceStudentClass in myCourseSorceStudentClasses
join myTeacher in myDB.Users
on myCourseSorceStudentClass.UserName equals myTeacher.UserName
into myTeacherCourseSorceStudentClasses
//獲得該學生的學生信息:班級、姓名和學號
from myTeacherCourseSorceStudentClass in myTeacherCourseSorceStudentClasses
select new SchoolMgr.Model.SorceTable
{
ClassName = myCourseSorceStudentClass.CourseName,
StudentID = StudentID,
StudentName = myStudentClass.StudentName,
CourseName = myCourseSorceStudentClass.CourseName,
TeacherName = myTeacherCourseSorceStudentClass.UserNickName,
SorceNumber = mySorceStudentClass.Sorce
};
return sorceTable;//返回成績單表
//改:以下以修改成績單中的成績爲例。
SchoolMgr.Model.SchoolMgrDataSetDataContext myDB =
new Model.SchoolMgrDataSetDataContext();
SchoolMgr.Model.Sorces mySorceLog =
myDB.Sorces.FirstOrDefault(p => p.SorceID == SorceID);
//在成績單表中找到該記錄
if (mySorceLog != null)//如果存在該記錄,則修改成績
{
try
{
mySorceLog.Sorce = SorceNumber;//修改成績
myDB.SubmitChanges();//提交到數據庫
return true;//修改成功,返回true
}
catch { }
}
return false;//修改失敗或不存在該記錄返回false
3.表示層(界面、功能設計部分)
在這個部分,主要是對應用具體功能的實現部分,包括登錄驗證、各種控件的數據綁定、成績錄入、條件查詢、成績分析等功能的代碼實現部分。
//登錄驗證部分代碼
if (TextboxUserName.Text.Trim().Length <= 0)//驗證用戶名不爲空
{
TextboxUserName.Focus();
MessageBox.Show("請輸入用戶名!");
}
else if (TextboxPassword.Text.Trim().Length <= 0)//驗證密碼不爲空
{
TextboxPassword.Focus();
MessageBox.Show("請輸入密碼!");
}
else
{
SchoolMgr.Logic.Users myUsers = new Logic.Users();
if (myUsers.IsUser(TextboxUserName.Text, TextboxPassword.Text))
{
……//登錄成功
}
else
{
MessageBox.Show("用戶名、密碼輸入錯誤或該用戶不存在!");
//登錄失敗提示
}
}
//數據綁定:以課程選擇下拉框(ComboBoxList)的數據綁定爲例。
SchoolMgr.Logic.Courses myCourse = new Logic.Courses();//新建邏輯層的課程對象
ComboBoxCourse.DataSource = myCourse.GetCoursesList();//獲取課程列表
ComboBoxCourse.DisplayMember = "CourseName";//下拉框顯示的內容的屬性
ComboBoxCourse.ValueMember = "CourseID";//下拉框選項值的值屬性
ComboBoxCourse.SelectedIndex = -1;//當前選中的項的索引設置爲-1(未選中)
//數據錄入部分,以插入新的成績記錄或修改成績記錄爲例。
if (e.RowIndex >= 0)//如果被修改的行的索引大於等於0
{
DataGridViewRow myRow = DataGridViewSorce.Rows[e.RowIndex];//獲得被修改的行
SchoolMgr.Logic.Sorce mySorce = new Logic.Sorce();//新建邏輯層的成績對象
SchoolMgr.Logic.Courses myCourse = new Logic.Courses();//新建邏輯層的課程對象
int CourseID = myCourse.GetCourseIDByTeacherNameAndCourseName(
(string)myRow.Cells[4].Value, (string)myRow.Cells[3].Value
);//獲得被修改行的課程ID
bool isOK = mySorce.InsertOrUpdateSorceLog(
CourseID,
(string)myRow.Cells[1].Value,
(double)myRow.Cells[5].Value);//在數據庫中插入該記錄或更新該記錄的成績
……//提示語句,如果修改失敗則彈出框進行提示,提示用戶重新輸入合法的成績。
}
//成績查詢,以學生查詢自身學號下所用課程的成績爲例。
string studentID = TextboxStudentID.Text.Trim().toString();//從學號輸入框中獲得學生學號
SchoolMgr.Logic.Sorce mySorce = new Logic.Sorce();
var mySorceTable = mySorce.GetSorceTable(studentID);//獲取學生的所有課程的成績
if (mySorceTable != null)//返回的成績單不爲空
{
DataGridViewSorce.DataSource = mySorceTable;//將成績單顯示在主界面的表格中
}
else
{
MessageBox.Show("輸入的學號有誤,請重新輸入!");
//如果查詢的成績單爲空,則提示用戶輸入正確的學號。
}
//綜合統計查詢,下面以成績分析爲例。
double[] SorceNumber = new double[DataGridViewSorce.Rows.Count];
int i=0;
foreach (DataGridViewRow x in DataGridViewSorce.Rows)
{
SorceNumber[i] = (double)x.Cells[5].Value;//獲得成績表中的成績
i++;
}
SchoolMgr.Logic.Sorce mySorce = new Logic.Sorce();
int[] Analysisesult = mySorce.GetSorceAnalysis(SorceNumber);
//成績分析返回的結果,分別是不及格、及格、良好、優秀的4級的人數
i=DataGridViewSorce.Rows.Count;
Below60Label.Text =
string.Format("不及格(<60):{0}人,{1}%",
Analysisesult[0], Math.Round(Analysisesult[0] / i * 100.0, 2));
//以文字形式顯示成績分析結果
ChartSorceAnalysis.DataSource = Analysisesult;
//以圖片形式顯示結果
三. 程序運行效果圖
1.登錄功能
啓動本應用,首先我們需要輸入用戶名和密碼,每個用戶的用戶名和密碼都在數據庫中記錄,其中用戶的密碼會以加密的方式在數據庫中記錄,如圖1所示。圖1 以加密的形式記錄用戶密碼
圖2 輸入用戶名和密碼
圖3 登錄成功
圖4 主界面
2. 增:以插入成績記錄到成績表中爲例
打開菜單欄的“開始”,點擊“新建成績單”,就會彈出新建成績單窗口,選擇課程和班級,選中需要記錄成的學生名單,如圖5所示。點擊“進入成績錄入”,成績單表格將會在主界面中顯示,如圖6所示。
圖4 “開始”菜單
圖7 插入或修改成績成功的提示
3.查:以“打開成績單”爲例
打開菜單欄的“開始”,點擊“打開成績單”,就會彈出打開成績單窗口,選擇課程或班級中的一個或兩個條件,如圖9所示。點擊“打開成績單”,成績單表格將會在主界面中顯示。
圖8 打開成績單窗口
4. 條件查詢:以“按班級查詢”或“按課程名稱”查詢學生成績爲例
打開菜單欄的“查詢”,點擊“按課程查詢成績”,如圖10所示,就會彈出課程選擇窗口,選擇課程,如圖11所示。點擊“打開成績單”,將會在主界面中顯示選中課程的所有學生的成績單。圖10 打開成績單窗口
圖11 打開成績單窗口
類似地,“按班級查詢成績”實現的功能與“按課程查詢成績”類似。個性化查詢則提供了6個不同的條件的單條件查詢,如圖12所示。點擊“查詢成績”,將會在主界面中顯示對應條件下的成績單。
打開菜單欄的“分析”,點擊“成績分析”,應用將會在對當前打開的成績單進行成績分析,包括文字、餅圖和柱狀圖的成績分析,如圖14~16所示。
圖13 個性化查詢成績
圖14 文字成績分析
圖15 柱狀圖成績分析
圖16 餅圖成績分析