三层架构,也有人叫做三层结构,是一种软件架构。
我这里将会以我自己写的一个ASP.NET三层架构为例子来学习理解它。刚开始学习.NET的时候,老师教的就是三层架构,但是三层架构不是万能的,也不是你写所有的.NET程序都用三层架构。我觉得最重要的是通过自己去学习别人的项目,自己亲自动手去写它来理解其中的架构思想。每一种架构思想,基本上都可以在不同的语言环境下面实现,而且当你通过自己的理解去实现它的时候你会有不一样的认识。
我这里所有写的都是以我自己的认识理解写的,我是一个菜鸟,也是一个程序猿,但我深爱着IT。如果有哪里不正确或者不当的地方,可以随便提出来或者联系我,交流中共同进步!我所写的是一个学生作业管理系统,利用ASP.net编写,整个软件架构使用了三层架构,前端框架使用了Bootstrap。源码直接点击此处下载。如果想对.NET三层架构有深入了解的,我推荐动力启航(http://www.dtcms.net/)大家可以去学习一下。
第一步,在我们建立.NET三层架构之前,我们得首先知道这三层分别的用处。
表现层:可以和用户直接接触的一层,如果你写B/S模式下的三层架构,那么表现层通俗的理解为就是我们所看到的web页面。表现层可以显示数据和接收用户输入的数据,为用户提供一种交互界面。
业务逻辑层:这一层也算是你的业务处理中最重要的,如果你的业务比较的繁琐,这一层是核心。一般我们进行开发,这一层主要集中在业务规则的制定、业务流程的实现等与业务需求有关的系统设计。
数据访问层:其实从字面我们就知道这一层用来进行数据库的访问,这里要注意的是,这里除了数据库之外,我们的文本文件、XML文档也算是数据,对其的访问也可以是叫做数据访问。比如在我的项目里面我会将一些系统的配置保存到xml文件里面。
第二步,新建asp.net项目,在新建项目之前,首先要对我们的项目的命名有个统一的规范,包括自己项目当中的参数命名、数据库命名等都要有一个统一的命名规范,写一个规范的项目,我个人觉得命名是第一步。对于C#的命名规范这里不过多的讲解。
我的解决方案的项目整个如下图所示:
其中XGhms.BLL表示业务逻辑层、XGhms.DAL表示数据访问层、XGhms.Web表示UI表现层。虽然这几层就可以简单的组成一个项目,但是往往在实际开发当中,我们还要考虑别的方面,比如如何的节省开发,如果该系统要与别的系统多对接该如何实现等等,所以XGhms.Helper是一个公共的层,里面包括了公共的一些方法,比如字符串的加密、XML文档的操作等。XGhms.Model层是一个模型(实体类),在三层之间传递数据的,我这里Model层里面的每一个类对应数据库里面的每一张表,这样方面操作。XGhms.Web.Services是为了后面网站如果进行与别的系统做对接或者提供提供相应的接口服务,都可以在里面实现。
第三步,每个项目开始之前,最重要的还是做需求分析,比如我的学生作业管理系统,你要花大量的时间去了解和实际的去调查,需求做好才能进行下面的工作。这里就不做大量的解说,如果后面有时间了专门写博探讨需求分析上面的事宜。
这是数据库的设计,这张关系图画的将就一下吧,o(╯□╰)o 数据库的源码都可以直接下载的。
第四步,关于Model层还有BLL层和DAL层前面讲了,现在有好多的软件可以直接生成这些层,不用我们去敲代码,比如动软代码生成器,但是我认为第一次去学习三层架构,代码还是自己动手去敲的比较好。
下面这是Model层的代码示例:
using System;
namespace XGhms.Model
{
public partial class course
{
private int _id;
///
/// 自增ID
///
public int id
{
get { return _id; }
set { _id = value; }
}
private string _course_number;
///
/// 课程号码(专业课程编码)
///
public string course_number
{
get { return _course_number; }
set { _course_number = value; }
}
private string _course_name;
///
/// 课程名称
///
public string course_name
{
get { return _course_name; }
set { _course_name = value; }
}
private int _term_id;
///
/// 学期ID
///
public int term_id
{
get { return _term_id; }
set { _term_id = value; }
}
private string _teacher;
///
/// 课程老师(主教)
///
public string teacher
{
get { return _teacher; }
set { _teacher = value; }
}
private string _other_teacher;
///
/// 助教
///
public string other_teacher
{
get { return _other_teacher; }
set { _other_teacher = value; }
}
private string _student_leader;
///
/// 该课程学生负责人
///
public string student_leader
{
get { return _student_leader; }
set { _student_leader = value; }
}
private string _course_info;
///
/// 该课程的信息
///
public string course_info
{
get { return _course_info; }
set { _course_info = value; }
}
private int _college_id;
///
/// 学院ID
///
public int college_id
{
get { return _college_id; }
set { _college_id = value; }
}
}
}
DAL层代码示例:
using System;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using XGhms.Helper;
namespace XGhms.DAL
{
///
/// 数据访问类:course
///
public partial class course
{
#region 基本方法=============================================
///
/// 是否存在该记录
///
/// ID
/// true or false
public bool Exists(int id)
{
StringBuilder strSql = new StringBuilder();
strSql.Append("select count(1) from xg_course");
strSql.Append(" where id=@id ");
SqlParameter[] parameters = {
new SqlParameter("@id", SqlDbType.Int,4)};
parameters[0].Value = id;
return SQLHelper.Exists(strSql.ToString(), parameters);
}
///
/// 根据课程ID和老师ID检查是否存在该课程
///
/// 课程ID
/// 老师ID
/// 是否存在
public bool Exists(int id, int teacherID)
{
StringBuilder strSql = new StringBuilder();
strSql.Append("select count(1) from xg_course");
strSql.Append(" where id="+id);
strSql.Append(" and teacher='" + teacherID + "'");
return SQLHelper.Exists(strSql.ToString());
}
///
/// 根据ID来删除相应的数据
///
/// ID
/// true or false
public bool Delete(int id)
{
StringBuilder strSql = new StringBuilder();
strSql.Append("delete from xg_course ");
strSql.Append(" where id=@id");
SqlParameter[] parameters = {
new SqlParameter("@id", SqlDbType.Int,4)};
parameters[0].Value = id;
int rows = SQLHelper.ExecuteSql(strSql.ToString(), parameters);
if (rows > 0)
{
return true;
}
else
{
return false;
}
}
///
/// 查询id得到一个对象实体
///
/// 课程id
/// model对象
public Model.course GetModel(int id)
{
SqlParameter[] parameters = {
new SqlParameter("@id", SqlDbType.Int,4)};
parameters[0].Value = id;
Model.course model = new Model.course();
DataSet ds = SQLHelper.SelectSqlReturnDataSet("course_SelectCourseById", parameters, CommandType.StoredProcedure);
if (ds.Tables[0].Rows.Count > 0)
{
if (ds.Tables[0].Rows[0]["id"] != null && ds.Tables[0].Rows[0]["id"].ToString() != "")
{
model.id = int.Parse(ds.Tables[0].Rows[0]["id"].ToString());
}
if (ds.Tables[0].Rows[0]["course_number"] != null && ds.Tables[0].Rows[0]["course_number"].ToString() != "")
{
model.course_number = ds.Tables[0].Rows[0]["course_number"].ToString();
}
if (ds.Tables[0].Rows[0]["course_name"] != null && ds.Tables[0].Rows[0]["course_name"].ToString() != "")
{
model.course_name = ds.Tables[0].Rows[0]["course_name"].ToString();
}
if (ds.Tables[0].Rows[0]["term_id"] != null && ds.Tables[0].Rows[0]["term_id"].ToString() != "")
{
model.term_id = int.Parse(ds.Tables[0].Rows[0]["term_id"].ToString());
}
if (ds.Tables[0].Rows[0]["teacher"] != null && ds.Tables[0].Rows[0]["teacher"].ToString() != "")
{
model.teacher = ds.Tables[0].Rows[0]["teacher"].ToString();
}
if (ds.Tables[0].Rows[0]["other_teacher"] != null && ds.Tables[0].Rows[0]["other_teacher"].ToString() != "")
{
model.other_teacher = ds.Tables[0].Rows[0]["other_teacher"].ToString();
}
if (ds.Tables[0].Rows[0]["student_leader"] != null && ds.Tables[0].Rows[0]["student_leader"].ToString() != "")
{
model.student_leader = ds.Tables[0].Rows[0]["student_leader"].ToString();
}
if (ds.Tables[0].Rows[0]["course_info"] != null && ds.Tables[0].Rows[0]["course_info"].ToString() != "")
{
model.course_info = ds.Tables[0].Rows[0]["course_info"].ToString();
}
if (ds.Tables[0].Rows[0]["college_id"] != null && ds.Tables[0].Rows[0]["college_id"].ToString() != "")
{
model.college_id = int.Parse(ds.Tables[0].Rows[0]["college_id"].ToString());
}
return model;
}
else
{
return null;
}
}
///
/// 插入新的课程(管理员插入)
///
/// 课程编号
/// 课程名
/// 学期ID
/// 老师ID
/// 学院ID
/// 受影响的行数
public int Insert(string course_number, string course_name,int tremID,int terID,int collegeID)
{
StringBuilder str = new StringBuilder();
str.Append("INSERT INTO [xg_course]([course_number],[course_name],[term_id],[teacher],[college_id])");
str.Append(" VALUES(@course_number,@course_name,");
str.Append(tremID+",");
str.Append("'"+terID+"',");
str.Append(collegeID+")");
SqlParameter[] parameters = {
new SqlParameter("@course_number", SqlDbType.NVarChar,50),
new SqlParameter("@course_name",SqlDbType.NVarChar,50)};
parameters[0].Value = course_number;
parameters[1].Value = course_name;
return SQLHelper.ExecuteSql(str.ToString(), parameters);
}
///
/// 老师更新课程信息
///
/// 课程ID
/// 助教ID
/// 学生ID
/// 课程信息
/// 受影响的行数
public int Update(int courseID, string oTerID, string stuID, string courInfo)
{
StringBuilder str = new StringBuilder();
str.Append("UPDATE [xg_course]");
str.Append(" SET other_teacher =@other_teacher,");
str.Append("student_leader =@student_leader,");
str.Append("course_info = @course_info");
str.Append(" where id=" + courseID);
SqlParameter[] parameters = {
new SqlParameter("@other_teacher", SqlDbType.NVarChar,100),
new SqlParameter("@student_leader",SqlDbType.NVarChar,50),
new SqlParameter("@course_info",SqlDbType.NVarChar,500)};
parameters[0].Value = oTerID;
parameters[1].Value = stuID;
parameters[2].Value = courInfo;
return SQLHelper.ExecuteSql(str.ToString(), parameters);
}
///
/// 根据课程的ID更新相应的课程
///
/// 课程ID
/// 课程编号
/// 课程名
/// 学期ID
/// 老师ID
/// 学院ID
/// 受影响的行数
public int UpdateOldCourse(int courseID, string course_number, string course_name, int tremID, int terID, int collegeID)
{
StringBuilder str = new StringBuilder();
str.Append("UPDATE [xg_course]");
str.Append(" SET [course_number] =@course_number,");
str.Append("[course_name] =@course_name,");
str.Append("[term_id] = " + tremID);
str.Append(",[teacher] = '" + terID+"'");
str.Append(",[college_id] = " + collegeID);
str.Append(" where id=" + courseID);
SqlParameter[] parameters = {
new SqlParameter("@course_number", SqlDbType.NVarChar,50),
new SqlParameter("@course_name",SqlDbType.NVarChar,50)};
parameters[0].Value = course_number;
parameters[1].Value = course_name;
return SQLHelper.ExecuteSql(str.ToString(), parameters);
}
///
/// 根据学期ID和学院ID获取课程数目
///
/// 课程ID
/// 学院ID
/// 课程数目
public int GetNumTotalByTremIdandCollegeID(int tremID,int collegeID)
{
string sql = "select count(id) from xg_course where term_id=" + tremID + " and college_id=" + collegeID;
object ob = SQLHelper.GetSingle(sql);
if (ob == null)
{
return 0;
}
else
{
return Convert.ToInt32(ob);
}
}
///
/// 根据学期和学院来分页显示课程
///
/// 学期ID
/// 学院ID
/// 开始的数目
/// 结束的数目
/// DataTable
public DataTable GetSelectByTremandCollegeandPage(int tremID, int collegeID, int PageBeginNum, int PageEndNum)
{
SqlParameter[] parameters = {
new SqlParameter("@term_id", SqlDbType.Int,6),
new SqlParameter("@college_id", SqlDbType.Int,6),
new SqlParameter("@PageBeginNum", SqlDbType.Int,6),
new SqlParameter("@PageEndNum", SqlDbType.Int,6)};
parameters[0].Value = tremID;
parameters[1].Value = collegeID;
parameters[2].Value = PageBeginNum;
parameters[3].Value = PageEndNum;
using (DataSet ds = SQLHelper.SelectSqlReturnDataSet("course_SelectByTremandCollegeandPage", parameters, CommandType.StoredProcedure))
{
return ds.Tables[0];
}
}
///
/// 根据学期和老师来查询课程
///
/// 老师ID
/// 学期ID
/// 课程列表
public DataTable GetCourseListByTerTrem(int terID, int tremID)
{
StringBuilder str = new StringBuilder();
str.Append("select id from xg_course where");
str.Append(" term_id=" + tremID);
str.Append(" and teacher='" + terID + "'");
using (DataSet ds = SQLHelper.Query(str.ToString()))
{
return ds.Tables[0];
}
}
///
/// 根据学期和学生ID来获取课程列表
///
/// 学生ID
/// 学期ID
/// 课程列表
public DataTable GetCourseListByStuTrem(int stuID, int tremID)
{
StringBuilder str = new StringBuilder();
str.Append("select xg_course.id from xg_course,xg_course_student ");
str.Append("where xg_course.id=xg_course_student.course_id and xg_course_student.student_id=" + stuID);
str.Append(" and term_id=" + tremID);
using (DataSet ds = SQLHelper.Query(str.ToString()))
{
return ds.Tables[0];
}
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace XGhms.BLL
{
///
/// 课程管理
///
public partial class course
{
DAL.course_student courstuDal = new DAL.course_student();
DAL.course coursDal = new DAL.course();
///
/// 根据课程ID和老师ID检查是否存在该课程
///
/// 课程ID
/// 老师ID
/// 是否存在
public bool Exists(int id, int teacherID)
{
return coursDal.Exists(id, teacherID);
}
///
/// 查询id得到一个对象实体
///
/// 课程id
/// model对象
public Model.course GetModel(int id)
{
return coursDal.GetModel(id);
}
public List GetCourListOfstuID(int stuID,int pageBeginNum,int pageEndNum)
{
DataTable courListDT = courstuDal.GetListOfStuID(stuID, pageBeginNum, pageEndNum);
List listModel=new List();
for (int i = 0; i < courListDT.Rows.Count; i++)
{
Model.course courModel=coursDal.GetModel(Convert.ToInt32(courListDT.Rows[i][0]));
listModel.Add(courModel);
}
return listModel;
}
///
/// 根据ID来删除相应的数据
///
/// ID
/// true or false
public bool Delete(int id)
{
return coursDal.Delete(id);
}
public bool Exists(int id)
{
return coursDal.Exists(id);
}
///
/// 插入新的课程(管理员插入)
///
/// 课程编号
/// 课程名
/// 学期ID
/// 老师ID
/// 学院ID
/// 受影响的行数
public int Insert(string course_number, string course_name, int tremID, int terID, int collegeID)
{
return coursDal.Insert(course_number, course_name, tremID, terID, collegeID);
}
///
/// 根据课程的ID更新相应的课程
///
/// 课程ID
/// 课程编号
/// 课程名
/// 学期ID
/// 老师ID
/// 学院ID
/// 受影响的行数
public int UpdateOldCourse(int courseID, string course_number, string course_name, int tremID, int terID, int collegeID)
{
return coursDal.UpdateOldCourse( courseID, course_number, course_name, tremID, terID, collegeID);
}
///
/// 根据学期ID和学院ID获取课程数目
///
/// 课程ID
/// 学院ID
/// 课程数目
public int GetNumTotalByTremIdandCollegeID(int tremID, int collegeID)
{
return coursDal.GetNumTotalByTremIdandCollegeID(tremID, collegeID);
}
///
/// 根据学期和学院来分页显示课程
///
/// 学期ID
/// 学院ID
/// 开始的数目
/// 结束的数目
/// DataTable
public DataTable GetSelectByTremandCollegeandPage(int tremID, int collegeID, int PageBeginNum, int PageEndNum)
{
return coursDal.GetSelectByTremandCollegeandPage( tremID, collegeID, PageBeginNum, PageEndNum);
}
///
/// 根据学期和老师来查询课程
///
/// 老师ID
/// 学期ID
/// 课程列表
public DataTable GetCourseListByTerTrem(int terID, int tremID)
{
return coursDal.GetCourseListByTerTrem(terID, tremID);
}
///
/// 老师更新课程信息
///
/// 课程ID
/// 助教ID
/// 学生ID
/// 课程信息
/// 受影响的行数
public int Update(int courseID, string oTerID, string stuID, string courInfo)
{
return coursDal.Update(courseID, oTerID, stuID, courInfo);
}
///
/// 根据学期和学生ID来获取课程列表
///
/// 学生ID
/// 学期ID
/// 课程列表
public DataTable GetCourseListByStuTrem(int stuID, int tremID)
{
return coursDal.GetCourseListByStuTrem(stuID, tremID);
}
}
}
前端页面代码示例:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="MyCourse.aspx.cs" Inherits="XGhms.Web.Teacher.CourseControls.MyCourse" %>
<%@ Register TagPrefix="uctrols" TagName="terTopNav" Src="~/Teacher/MyControls/TerTopNav.ascx" %>
<%@ Register TagPrefix="uctrols" TagName="terLeftNav" Src="~/Teacher/MyControls/TerLeftNav.ascx" %>
<%@ Register TagPrefix="uctrols" TagName="downFooter" Src="~/MyControls/DownFooter.ascx" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>我的课程 - XGhms</title>
<link href="../../Style/bootstrap.css" rel="stylesheet" type="text/css" />
<link href="../../Style/site.css" rel="stylesheet" type="text/css" />
<link href="../../Style/bootstrap-responsive.css" rel="stylesheet" type="text/css" />
<!--[if lt IE 9]>
<script src="http://cdn.bootcss.com/html5shiv/3.7.0/html5shiv.min.js"></script>
<![endif]-->
</head>
<body>
<form id="form1" runat="server">
<uctrols:terTopNav ID="topNav" runat="server" />
<div class="container-fluid">
<div class="row-fluid">
<uctrols:terLeftNav ID="leftNav" runat="server" />
<div class="span9">
<div class="row-fluid">
<div class="page-header">
<h1><span id="title_h1">我的课程</span> <small id="h1small"> </small></h1>
</div>
<div id="oneDiv" class="form-horizontal">
<fieldset>
<div class="control-group">
<label class="control-label" for="collegeName">选择学期</label>
<div class="controls">
<select onchange="SelectTerm()" id="selTerm"><option value="0">请选择</option></select>
</div>
</div>
</fieldset>
</div>
<table class="table table-striped table-bordered table-condensed" style="width:95%">
<thead>
<tr>
<th>ID</th>
<th>课程编号</th>
<th>课程名</th>
<th>课程老师</th>
<th>所在学院</th>
<th>操作</th>
</tr>
</thead>
<tbody id="defaultAddTr">
</tbody>
</table>
</div>
</div>
</div>
<uctrols:downFooter ID="AllDownFooter" runat="server" />
</div>
</form>
</body>
</html>
<script type="text/javascript">
$(function () {
$("#left_nav_ul li:eq(4)").attr('class', 'active'); //获取相应的li,设置class为active
$.ajax({ //添加学期
type: "post",
dataType: "json",
url: "/Handles/TeacherHandler.ashx",
data: "action=GetAllTermForNow",
success: function (data) {
$.each(data.termList, function (index, item) {
if (item.termCheck == 1) {
col_addSelect("#selTerm", item.id, item.termName, item.id);
$('#h1small').append(item.termName);
GetCourselistByTrem(item.id);
}
else {
col_add("#selTerm", item.id, item.termName);
}
});
}
});
});
//当学期选项变化时候
function SelectTerm() {
if ($('#selTerm option:selected').val() == 0) {
return;
}
$('#defaultAddTr').empty();
$('#h1small').empty();
$('#h1small').append($('#selTerm option:selected').text());
GetCourselistAll();
}
//查询数据
function GetCourselistByTrem(tremID) {
$.ajax({ //获取当前的查询条件下面的条数
type: "post",
dataType: "json",
async: false,
url: "/Handles/TeacherHandler.ashx",
data: "action=GetTerCourseByTrem&tremID=" + tremID,
success: function (data) {
$.each(data.courseList, function (index, item) {
AddTrList(item.id, item.course_number, item.course_name, item.teacher, item.college);
});
}
});
}
//查询数据
function GetCourselistAll() {
var tremID = $('#selTerm option:selected').val();
$.ajax({ //获取当前的查询条件下面的条数
type: "post",
dataType: "json",
async: false,
url: "/Handles/TeacherHandler.ashx",
data: "action=GetTerCourseByTrem&tremID=" + tremID,
success: function (data) {
$('#defaultAddTr').empty();
$.each(data.courseList, function (index, item) {
AddTrList(item.id, item.course_number, item.course_name, item.teacher, item.college);
});
}
});
}
function AddTrList(ID, courseNum, courseName, teacher, collegeName) {
var newHW = '<li><a href="CourseManage.aspx?id=' + ID + '"><i class="icon-pencil"></i> 修改课程</a></li><li><a href="../HomeWorkControls/HomeWorkManage.aspx?cid=' + ID + '"><i class="icon-plus-sign"></i> 添加作业</a></li><li><a href="CourseStatistics.aspx?id=' + ID + '"><i class="icon-signal"></i> 作业统计</a></li>';
$('#defaultAddTr').append('<tr class="list-users"><td>' + ID + '</td><td>' + courseNum + '</td><td>' + courseName + '</td><td>' + teacher + '</td><td>' + collegeName + '</td><td><div class="btn-group"><a class="btn btn-mini dropdown-toggle" data-toggle="dropdown" href="#">操作 <span class="caret"></span></a><ul class="dropdown-menu">' + newHW + '</ul></div></td></tr>');
}
// 添加下拉列表选项根据已选择的
function col_addSelect(selectobj, value, text, selectValue) {
var selObj = $(selectobj);
if (value == selectValue) {
selObj.append("<option selected='selected' value='" + value + "'>" + text + "</option>");
} else {
selObj.append("<option value='" + value + "'>" + text + "</option>");
}
}
// 添加下拉列表选项
function col_add(selectobj, value, text) {
var selObj = $(selectobj);
selObj.append("<option value='" + value + "'>" + text + "</option>");
}
// 删除
function col_delete(selectobj) {
var selOpt = $(selectobj + " option:selected");
selOpt.remove();
}
// 清空下拉列表选项并且加一个全选的按钮
function col_clear(colobject) {
var selOpt = $(colobject + " option");
selOpt.remove();
col_add(colobject, 0, "请选择"); //默认添加有全部请选择的选项
}
</script>