三层架构
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2QvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2LcZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39TO5gTO0QTM3EjMwUDM2EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
DAL数据访问层: BooksRatingService各种service类定义各种使用sqlhelper定义数据库的操作方法将sql字段加载进去各种具体的数据操作的方法
BLL逻辑业务层:BookManager各种manager类调用DAL层类方法定义对model类的操作方法
models实体类:定义实体类 设置 获得方法,数据传输的中间媒介
web层:视图文件,布局 脚本 样式,aspx文件布局+aspx.cs文件进行数据与控件的交互
DAL中的sqlhelper定义数据库操作方法
Bin文件夹中引用dll文件
问题:
为何需要BLL 层?不直接调用DAL中的方法,
model类代码:作为数据操作媒介
private DateTime createdTime;
public DateTime CreatedTime
{
get { return createdTime; }
set { createdTime = value; }
}
SqlHelper类代码:定义数据操作方法
Method:readData DataSet Query sqlcmd
Reader_data:ExecuteReader()
DataSet:ExecuteDataset()
Query_Data: ExecuteNonQuery(),
insertData: ExecuteScalar()
Sqlcmd_execute: PrepareCommand()
//Databaseconnection strings
public static readonly string ConnectionString = ConfigurationManager.ConnectionStrings["BookShop"].ConnectionString;
ExecuteNonQuery
///<summary>
///执行SqlServer存储过程
///注意:不能执行有out 参数的存储过程
///</summary>
///<paramname="connectionString">连接字符串</param>
///<paramname="spName">存储过程名</param>
///<paramname="parameterValues">对象参数</param>
///<returns>受影响的行数</returns>
public static int ExecuteNonQuery(string connectionString, string spName, params object[] parameterValues)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, conn, spName,parameterValues);
int val =cmd.ExecuteNonQuery();
return val;
}
}
ExecuteReader
///<summary>
/// 执行sql命令
///</summary>
///<paramname="connectionString">连接字符串</param>
///<paramname="commandType">命令类型</param>
///<paramname="commandText">sql语句/参数化sql语句/存储过程名</param>
///<paramname="commandParameters">参数</param>
///<returns>SqlDataReader 对象</returns>
public static SqlDataReader ExecuteReader(string connectionString, CommandType commandType, string commandText, params SqlParameter[]commandParameters)
{
SqlConnection conn = new SqlConnection(connectionString);
try
{
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd,commandType, conn, commandText, commandParameters);
SqlDataReader rdr =cmd.ExecuteReader(CommandBehavior.CloseConnection);
return rdr;
}
catch
{
conn.Close();
throw;
}
}
ExecuteDataset
//setthe data to the dataAdapter
public static DataSet ExecuteDataset(string connectionString, string spName, params object[] parameterValues)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, conn,spName, parameterValues);
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}
}
}
ExecuteScalar
///<summary>
///执行Sql命令
///</summary>
///<paramname="connectionString">连接字符串</param>
///<paramname="commandType">命令类型</param>
///<param name="commandText">sql语句/参数化sql语句/存储过程名</param>
///<paramname="commandParameters">参数</param>
///<returns>执行结果对象</returns>
public static object ExecuteScalar(string connectionString, CommandType commandType, string commandText, params SqlParameter[]commandParameters)
{
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn = new SqlConnection(connectionString))
{
PrepareCommand(cmd,commandType, conn, commandText, commandParameters);
object val =cmd.ExecuteScalar();
return val;
}
}
PrepareCommand
///<summary>
///设置一个等待执行的SqlCommand对象
///</summary>
///<paramname="cmd">SqlCommand 对象,不允许空对象</param>
///<paramname="conn">SqlConnection 对象,不允许空对象</param>
///<paramname="commandText">Sql 语句</param>
///<paramname="cmdParms">SqlParameters 对象,允许为空对象</param>
private static void PrepareCommand(SqlCommand cmd, CommandType commandType, SqlConnection conn, string commandText, SqlParameter[] cmdParms)
{
//打开连接
if (conn.State != ConnectionState.Open)
conn.Open();
//设置SqlCommand对象
cmd.Connection = conn;
cmd.CommandText = commandText;
cmd.CommandType = commandType;
if (cmdParms != null)
{
foreach (SqlParameter parm in cmdParms)
cmd.Parameters.Add(parm);
}
}
DAL类代码:cast datas to models
设置/获得参数,传入sqlhelper方法 得到数据映射到实体类 用实体类对数据进行具体操作
Method:
get list of items:GetBookRatings(int bookId),GetBookRatings(string safeSql)
insert Data: AddBookRating()
get Data: GetBookRatings()
BooksRatingService:
//database connection strings
string connection =ConfigurationManager.ConnectionStrings["BookShop"].ConnectionString;
AddBookRating
//method: insert data by casting datato models
public bool AddBookRating(BookRatings bookrating)
{
string sql =
"INSERTBookRatings (BookId,UserId,Rating,Comment)" +
"VALUES(@BookId, @UserId, @Rating, @Comment)";
sql += " ; [email protected]@IDENTITY";
SqlParameter[] para = new SqlParameter[]
{
new SqlParameter("@BookId",bookrating.BookId),
new SqlParameter("@UserId",bookrating.User.Id),
new SqlParameter("@Rating",bookrating.Rating),
new SqlParameter("@Comment",bookrating.Comment)
};
bookrating.Id = Convert.ToInt32(SqlHelper.ExecuteScalar(this.connection, CommandType.Text, sql, para));
return bookrating.Id >0;
}
GetBookRatings
//method:getspecially data according to terms
///<summary>
///根据书的Id得到其评价信息
///</summary>
///<paramname="bookId"></param>
///<returns></returns>
//getbookRatings list of specially book by id
public List<BookRatings> GetBookRatings(int bookId)
{
string sql = "select * frombookratings where bookid='" + bookId + "'";
return this.GetBookRatings(sql);
}
//getlist of bookRatings by sql
private List<BookRatings> GetBookRatings(string safeSql)
{
List<BookRatings> list = new List<BookRatings>();
DataSet ds = SqlHelper.ExecuteDataset(this.connection, CommandType.Text, safeSql);
if (ds.Tables.Count> 0)
{
DataTable dt = ds.Tables[0];
//castdata to models by traversing dataRow
foreach (DataRow row in dt.Rows)
{
BookRatings brating = new BookRatings();
brating.Id = (int)row["Id"];
brating.BookId = (int)row["BookId"];
brating.Rating = (int)row["Rating"];
int userId = (int)row["userid"];
brating.User = new UserService().GetUserById(userId);
brating.Comment = (string)row["Comment"];
brating.CreatedTime = (DateTime)row["CreatedTime"];
list.Add(brating);
}
}
return list;
}
GetCategoryById
//cast data to model
public Category GetCategoryById(Int32 id)
{
string sql = "SELECT * FROMCategories WHERE Id = @Id";
Category category = null;
using (SqlDataReader reader = SqlHelper.ExecuteReader(SqlHelper.ConnectionString, CommandType.Text, sql, new SqlParameter("@Id", id)))
{
if (reader.Read())
{
category = new Category();
category.Id = (int)reader["Id"];
category.Name = (string)reader["Name"];
category.PId = (int)reader["PId"];
}
}
return category;
}
BLL类代码:get and set models List
Get models list
public List<Category> GetCategories()
{
//调用DAL类方法返回实体类列表
return new CategoryService().GetCategories();
}
Set Models list
public void AddCategory(Category category)
{
//调用DAL类方法定义添加实体类
new CategoryService().AddCategory(category);
}
Get specially terms of models list byparameter
public List<BookRatings> GetBookRatings(int bookId)
{
return new BooksRatingService().GetBookRatings(bookId);
}
Web
Common.master 通用视图 用于引用提高代码重用度
Common.master.cs 从数据库读取数据定义视图
Admin.master 管理者通用视图
Admin.master.cs 从数据库读取数据定义视图
#region Method_name
代码显示缩进
#endregion
注释:说明方法用途,参数,返回对象
///<summary>
///执行Sql命令
///</summary>
///<paramname="connectionString">连接字符串</param>
///<paramname="commandType">命令类型</param>
///<paramname="commandText">sql语句/参数化sql语句/存储过程名</param>
///<paramname="commandParameters">参数</param>
///<returns>DataSet 对象</returns>
App_code: Category.cs
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public int Pid { get; set; }
public int SortNum { get; set; }
}
Web.Config
<configuration>
<connectionStrings>
<addname="BookShop"connectionString="server=.;uid=sa;pwd=sa;database=BookShopPlus"/>
</connectionStrings>
<system.web>
<compilationdebug="true"targetFramework="4.0"/>
</system.web>
</configuration>
Web.SiteMap
<siteMapxmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNodeurl="~\Default.aspx"title="第三波" description="">
<siteMapNodeurl="BookList.aspx"title="图书列表页" description=""/>
<siteMapNodeurl="Search.aspx"title="搜索页" description=""/>
<siteMapNodeurl=""title="订单查询" description="" />
<siteMapNodeurl="ShoppingCart.aspx"title="购物车" description="" />
<siteMapNodeurl="~\BookDetail.aspx"title="图书详细页" description="" />
<siteMapNodeId=""url=""title="会员后台"description="">
<siteMapNodeurl="~\Membership\Register.aspx" title="用户注册" description="" />
<siteMapNodeurl="~\Membership\Login.aspx" title="用户登录" description="" />
<siteMapNodeurl="~\Membership\UserModify.aspx"title="修改个人信息" description="" />
<siteMapNodeurl="" title="退出登录" description="" />
</siteMapNode>
<siteMapNodeId=""url="~\Admin\Default.aspx"title="管理员后台"description="">
<siteMapNodeurl=""title="用户管理"description="">
<siteMapNodeurl="~\Admin\UserList.aspx"title="管理用户"description="" />
<siteMapNodeurl="~\Admin\UserStateManage.aspx"title="状态管理"description="" />
<siteMapNodeurl="~\Admin\UserDetails.aspx" title="修改用户资料" description="" />
</siteMapNode>
<siteMapNodeurl=""title="图书管理"description="">
<siteMapNodeurl="~\Admin\CategoryManage.aspx"title="添加图书分类"description="" />
<siteMapNodeurl="~\Admin\BookCategory.aspx"title="为书籍分类"description="" />
<siteMapNodeurl="~\Admin\BookDetail.aspx"title="图书详细信息"description="" />
<siteMapNodeurl="~\Admin\BookList.aspx"title="图书列表"description="" />
<siteMapNodeurl="~\Admin\RecomBookList.aspx"title="推荐图书"description="" />
</siteMapNode>
<siteMapNodeurl=""title="订单管理"description="">
<siteMapNodeurl="~\Admin\OrderList.aspx"title="审核订单"description="" />
<siteMapNodeurl="~\Admin\OrderDetail.aspx"title="详细订单"description="" />
</siteMapNode>
<siteMapNodeurl="~\Membership\LoginOut.aspx"title="退出"description="管理员退出">
</siteMapNode>
</siteMapNode>
</siteMapNode>
</siteMap>
TreeView.xml
<Booksurl="default.aspx"title="新书推荐"description="">
<Booktitle=" C#"url="BookList.aspx?typeid=1"description="" />
<Booktitle=".NET"url="BookList.aspx?typeid=25"description="" />
<Booktitle="ASP.NET"url="BookList.aspx?typeid=29"description="" />
<Booktitle="Basic VB VB Script"url="BookList.aspx?typeid=16"description="" />
<Booktitle="C C++ VC VC++"url="BookList.aspx?typeid=15"description="" />
<Booktitle="CSS Div"url="BookList.aspx?typeid=4"description="" />
<Booktitle="HTML XML"url="BookList.aspx?typeid=22"description="" />
<Booktitle="J2EE"url="BookList.aspx?typeid=2"description="" />
<Booktitle="Java Script Java"url="BookList.aspx?typeid=21"description="" />
<Booktitle="JSP"url="BookList.aspx?typeid=31"description="" />
<Booktitle="Perl"url="BookList.aspx?typeid=26"description="" />
<Booktitle="WINDOWS"url="BookList.aspx?typeid=35"description="" />
<Booktitle="电子商务"url="BookList.aspx?typeid=38"description="" />
<Booktitle="计算机等级考试"url="BookList.aspx?typeid=17"description="" />
<Booktitle="计算机理论"url="BookList.aspx?typeid=20"description="" />
<Booktitle="其他"url="BookList.aspx?typeid=28"description="" />
<Booktitle="网站开发"url="BookList.aspx?typeid=27"description="" />
</Books>
Aspx代码
HTML+css+javascript布局
普通控件:
<label></label>
//表示空格
//页面链接
<a href="Register.aspx">还没有注册?</a>
//单选框
<input type="checkbox" name="" checked="checked" />
//图片链接
<img src="Images/login_in.gif" alt="会员登录" />
//调用css
<link href="Css/member.css" rel="stylesheet" type="text/css" />
//表单用form
<form id="form1" runat="server"></form>
//引用页面
<%@ Page Title=""Language="C#" MasterPageFile="~/Admin/Admin.master" AutoEventWireup="true"CodeFile="Default.aspx.cs" Inherits="Admin_Default" %>
//内容载体控件
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">管理员首页
</asp:Content>
Javascript
<script language="javascript">
function checkInput() {
var loginId =document.getElementById("txtLoginId").value;
if (loginId == "") {
alert("用户名不能为空");
return false;
}
var pwd =document.getElementById("txtLoginPwd").value;
var pwdAgain =document.getElementById("txtPwdAgain").value;
if (pwd != pwdAgain) {
alert("两次输入的密码不一致");
return false;
}
return true;
}
</script>
<script language=javascript>
function selectAll(checkAll) {
var items =document.getElementsByTagName("input");
for (i = 0; i <items.length; i++) {
if (items[i].type == "checkbox") {
items[i].checked =checkAll.checked;
}
}
}
</script>
Asp控件:
//下拉框 数据来自属性中items
<asp:DropDownList ID="ddlCategory" runat="server" Width="172px" AutoPostBack="True" onselectedindexchanged="ddlCategory_SelectedIndexChanged1"/>
//输入框
<asp:TextBox ID="txtLoginPwd" runat="server" TextMode="Password" CssClass="opt_input"/>
//按钮
<asp:Button ID="btnRegister" runat="server" Text="确定了,马上提交" CssClass="opt_sub" onclick="btnRegister_Click" />
网格视图:列名来自属性Columns,数据来自cs文件操作
<asp:GridView ID="gvBooks" runat="server" AllowPaging="True"
AutoGenerateColumns="False" BackColor="LightGoldenrodYellow" BorderColor="Tan"
BorderWidth="1px" CellPadding="2" ForeColor="Black" GridLines="None"
onpageindexchanging="gvBooks_PageIndexChanging"
onrowdatabound="gvBooks_RowDataBound" Width="771px">
<AlternatingRowStyle BackColor="PaleGoldenrod" />
<Columns>
<asp:TemplateField ItemStyle-Width="60px" ItemStyle-HorizontalAlign=Center>
<HeaderTemplate>
<asp:CheckBox ID="CheckBox2" runat="server" Text="全选" onclick="selectAll(this)" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server" />
</ItemTemplate>
<ItemStyle HorizontalAlign="Center" Width="60px"></ItemStyle>
</asp:TemplateField>
<asp:BoundField DataField="Title" HeaderText="书名" />
<asp:BoundField DataField="author" HeaderText="作者" />
<asp:TemplateField HeaderText="出版社"></asp:TemplateField>
<asp:BoundField DataField="UnitPrice" HeaderText="单价" />
</Columns>
<FooterStyle BackColor="Tan" />
<HeaderStyle BackColor="Tan" Font-Bold="True" />
<PagerStyle BackColor="PaleGoldenrod" ForeColor="DarkSlateBlue"
HorizontalAlign="Center" />
<SelectedRowStyle BackColor="DarkSlateBlue" ForeColor="GhostWhite" />
<SortedAscendingCellStyle BackColor="#FAFAE7" />
<SortedAscendingHeaderStyle BackColor="#DAC09E" />
<SortedDescendingCellStyle BackColor="#E1DB9C" />
<SortedDescendingHeaderStyle BackColor="#C2A47B" />
</asp:GridView>
树状结构:调用web.sitemap文件数据
<div id="subnav">
<asp:TreeView ID="TreeView1" runat="server" DataSourceID="SiteMapDataSource1">
</asp:TreeView>
<br />
<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server"
ShowStartingNode="False" StartingNodeUrl="~/Admin/Default.aspx" />
</div>
位置选择+内容控件
<div id="breadcrumb">您现在的位置:
<asp:SiteMapPath ID="SiteMapPath1" runat="server">
</asp:SiteMapPath>
</div>
<div >
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
判断是否为空
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
ControlToValidate="txtLoginPwd" ErrorMessage="密码不能为空"/>
两次密码相同
<asp:CompareValidator ID="CompareValidator1" runat="server"
ControlToCompare="txtLoginPwd" ControlToValidate="txtPwdAgain"
Display="Dynamic" ErrorMessage="两次密码不一致"/>
邮件格式
<asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" ControlToValidate="txtEmail" ErrorMessage="Email格式不正确" ValidationExpression="\w+([+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"/>
手机格式
<asp:RegularExpressionValidator ID="RegularExpressionValidator2" runat="server" ControlToValidate="txtPhone" ErrorMessage="手机号码格式不正确" ValidationExpression="1\d{10}"/>
出生日期格式
<asp:CompareValidator ID="CompareValidator2" runat="server" ControlToValidate="txtBirthday" ErrorMessage="出生日期格式不正确" Operator="LessThan" Type="Date"/>
提供验证码
<asp:TextBox ID="txtCode" CssClass="opt_input" runat="server"/>
<cc1:SerialNumber ID="snCode" runat="server"/>
Alert
<asp:Literal ID="litAlert" runat="server"/>
Aspx.cs代码:页面逻辑
//调用实体类和BLL层操作数据
using BookShop.BLL;
CategoryManager categoryManager = new CategoryManager();
BookManager bookManager = new BookManager();
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
bindCategory();
categoryId = Convert.ToInt32(ddlCategory.SelectedValue);
bindBooks();
}
}
set data to widget
private void bindCategory()
{
ddlCategory.DataSource =categoryManager.GetCategories();
ddlCategory.DataTextField = "Name";
ddlCategory.DataValueField = "Id";
ddlCategory.DataBind();
}
set data to gridView widget
private void bindBooks()
{
gvBooks.DataSource = bookManager.GetBooks(categoryId);
gvBooks.DataBind();
}
protected voidgvBooks_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Attributes.Add("onmouseover", "currentColor=this.style.backgroundColor;this.style.backgroundColor='red'");
e.Row.Attributes.Add("onmouseout", "this.style.backgroundColor=currentColor");
}
}
//
protected voidgvBooks_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
gvBooks.PageIndex = e.NewPageIndex;
categoryId = Convert.ToInt32(ddlCategory.SelectedValue);
bindBooks();
}
Category selectedIndexChaged
protected voidddlCategory_SelectedIndexChanged1(object sender, EventArgs e)
{
categoryId = Convert.ToInt32(ddlCategory.SelectedValue);
bindBooks();
}
onClickListener
UserManager userManager = new UserManager();
protected void btnLogin_Click(object sender, EventArgs e)
{
string loginId =txtLoginId.Text.Trim();
string loginPwd =txtLoginPwd.Text.Trim();
BookShop.Models.User user = new BookShop.Models.User();
string message = "";
if(userManager.Login(loginId, loginPwd, ref user, ref message))
{
if (user.UserRole.Name== "管理员")
Response.Redirect("~/Admin/Default.aspx");
else
Response.Redirect("~/Default.aspx");
}
else
{
Page.ClientScript.RegisterStartupScript(this.GetType(), "alertError", "<script>alert('" + message + "')</script>");
}
}
Note
//可以用Literal控件的Text属性存放脚本,客户端不会生成任何其他标记,只有脚本
// litAlert.Text ="<script>alert('验证码错误')</script>";
//可以用Label控件的Text属性存放脚本,但客户端会生成一个<span>标记来存放脚本
// lblAlert.Text ="<script>alert('验证码错误')</script>";
//将脚本生成在</form>之前 消息框弹出时可以看到页面其他内容
Page.ClientScript.RegisterStartupScript(this.GetType(), "jsCodeError", "<script>alert('验证码错误')</script>");
//将脚本生成在<form>标记之后 消息框弹出时看不到页面其他内容
//Page.ClientScript.RegisterClientScriptBlock(this.GetType(),"jsCodeError", "<script>alert('验证码错误')</script>");
//将脚本生成在Html的顶部 消息框弹出时看不到页面其他内容
//Response.Write("<script>alert('验证码错误')</script>");
方法实现:
SqlParameter
SqlParameter[] para = new SqlParameter[]
{
new SqlParameter("@BookId",bookrating.BookId),
new SqlParameter("@UserId",bookrating.User.Id),
new SqlParameter("@Rating",bookrating.Rating),
new SqlParameter("@Comment",bookrating.Comment)
};
SqlDataReader
using (SqlDataReader reader = SqlHelper.ExecuteReader(SqlHelper.ConnectionString, CommandType.Text, sql, new SqlParameter("@Id", id)))
{
if (reader.Read())
{
category = new Category();
category.Id = (int)reader["Id"];
category.Name = (string)reader["Name"];
category.PId = (int)reader["PId"];
}
}
Traverse to Get List
public List<BookRatings> GetBookRatings(int bookId)
{
return new BooksRatingService().GetBookRatings(bookId);
}
private List<BookRatings> GetBookRatings(string safeSql)
{
List<BookRatings> list = new List<BookRatings>();
DataSet ds = SqlHelper.ExecuteDataset(this.connection, CommandType.Text, safeSql);
if (ds.Tables.Count> 0)
{
DataTable dt = ds.Tables[0];
//castdata to models by traversing dataRow
foreach (DataRow row in dt.Rows)
{
BookRatings brating = new BookRatings();
brating.Id = (int)row["Id"];
brating.BookId = (int)row["BookId"];
brating.Rating = (int)row["Rating"];
int userId = (int)row["userid"];
brating.User = new UserService().GetUserById(userId);
brating.Comment = (string)row["Comment"];
brating.CreatedTime = (DateTime)row["CreatedTime"];
list.Add(brating);
}
}
return list;
}