打开VS2005的CAROA项目,第一个程序我就想做员工列表页面。以便熟悉和了解asp.net2.0中对数据库的操作和显示方法。
我的目的很明确,就是实现员工管理功能第一阶段要求:
列出所有部门(下拉列表)
选择部门列出相应员工(GridView,级联)
选择员工显示员工详细信息(DetailsView)
增加新部门(部门存在上下级关系)
修改部门名称
删除部门(该部门下必须没有员工)
增加新员工
修改员工信息
删除员工
1.首先进行数据库设计和范例数据的填充:
表Clerk
字段名 | 类型 | 说明 |
ClerkID | int | 主键 |
RealName | nvarchar() | 员工姓名 |
JobNum | nvarchar() | 员工工号 |
DeptID | int | 部门编号 |
表CODE_Dept
字段名 | 类型 | 说明 |
DeptID | int | 主键 |
DeptName | nvarchar() | 部门名称 |
ParentDeptID | int | 上级部门 |
AreaID | int | 地区编号 |
表CODE_Area
字段名 | 类型 | 说明 |
AreaID | int | 主键 |
AreaName | nvarchar() | 地区名称 |
在数据库关系图中,我们将Code_Area,Code_Dept,Clerk关联起来。
在表里面添加示例数据后,按照我们设定的目标开始进行编码!
2.怎样读取web.config中的数据库连接字串:
web.config中的数据库连接字串部分:
<configuration>
<appSettings/>
<connectionStrings>
<add name="CAROAConnectionString" connectionString="Data Source=192.xx.xx.xx;Initial Catalog=CAROA;Persist Security Info=True;User ID=xxx;Password=xxx" providerName="System.Data.SqlClient"/>
</connectionStrings>
.....
</configuration>
在DAL.cs数据访问层中读取如下(注DAL.cs是数据访问层的代码,主要用于完成最底层的数据库操作,来源于Microsoft Data Access Application Block for .NET):
public
static
readonly
string
CONN_STRING
=
System.Configuration.ConfigurationManager.ConnectionStrings[
"
CAROAConnectionString
"
].ConnectionString;
在表示层ClerkList.aspx的SqlDataSource中读取如下:
<
asp:SqlDataSource ID
=
"
SqlDataSource1
"
runat
=
"
server
"
ConnectionString
=
"
<%$ ConnectionStrings:CAROAConnectionString %>
"
SelectCommand = " SELECT * FROM [Clerk] " ></ asp:SqlDataSource >
SelectCommand = " SELECT * FROM [Clerk] " ></ asp:SqlDataSource >
使用Web.Configuration而非System.Configuration时代码如下:
using
System.Web.Configuration;
ConnectingStringSettings conn_string = WebConfigurationManager.ConnectionStrings[ " CAROAConnectionString " ];
或者
string conn_string = WebConfigurationManager.ConnectionStrings[ " CAROAConnectionString " ].ConnectionString;
ConnectingStringSettings conn_string = WebConfigurationManager.ConnectionStrings[ " CAROAConnectionString " ];
或者
string conn_string = WebConfigurationManager.ConnectionStrings[ " CAROAConnectionString " ].ConnectionString;
当然 如果要在项目中加密数据库连接字符串,可以这么做
D:\Program Files\Microsoft Visual Studio
8
\VC
>
aspnet_regiis
-
pe
"
connectionStrin
gs " -app " / CarOAWeb " -prov " RSAProtectedConfigurationProvider "
或者这么写
aspnet_regiis -pe "connectinStrings" -app "/CarOAWeb"
解密只需 将-pe 改成 -pd即可
前提是 项目站点使用IIS,并且为网站配置了虚拟目录
gs " -app " / CarOAWeb " -prov " RSAProtectedConfigurationProvider "
或者这么写
aspnet_regiis -pe "connectinStrings" -app "/CarOAWeb"
解密只需 将-pe 改成 -pd即可
否则会出现我这样的出错信息:
正在加密配置节
打不开虚拟路径“ / CarOAWeb”和站点“默认网站”的配置。
指定的参数已超出有效值的范围。
参数名: site
失败 !
打不开虚拟路径“ / CarOAWeb”和站点“默认网站”的配置。
指定的参数已超出有效值的范围。
参数名: site
失败 !
在ASP.NET 1.1中,我们一般是把连接字串写在<appSetting>之中,如下:
<
configuration
>
< appSettings />
< add key = " CAROAConnectionString " value = " Data Source=192.xx.xx.xx;Initial Catalog=CAROA;Persist Security Info=True;User ID=xxx;Password=xxx " providerName = " System.Data.SqlClient " />
</ appSettings >
..
</ configuration >
< appSettings />
< add key = " CAROAConnectionString " value = " Data Source=192.xx.xx.xx;Initial Catalog=CAROA;Persist Security Info=True;User ID=xxx;Password=xxx " providerName = " System.Data.SqlClient " />
</ appSettings >
..
</ configuration >
这时,读取设置的语句就是这样了(ASP.NET 2.0):
string
conn_string
=
System.Configuration.ConfigurationManager.AppSettings[
"
CAROAConnectionString
"
].ToString;
3.接下来打开数据库,执行选取所有员工sql语句
利用ADO.NET,我们是这样编写的:
首先在ClerkList.aspx中拖入一个GridView控件,ID是GridView1。
ClerkList.aspx.cs中代码如下:
using
System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class clerklist : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//创建连接字符串
string conn_string = System.Configuration.ConfigurationManager.ConnectionStrings["CAROAConnectionString"].ConnectionString;
//创建命令字符串
string comm_string = "select * from clerk";
//构造SqlDataAdapter对象
SqlDataAdapter dataAdapter = new SqlDataAdapter(comm_string, conn_string);
//创建一个DataSet对象
DataSet dataSet = new DataSet();
//填充DataSet对象
dataAdapter.Fill(dataSet, "Clerk");
//从DataSet中获取DataTable
DataTable dataTable = dataSet.Tables["Clerk"];
//将DataTable绑定到GridView
GridView1.DataSource = dataTable;
GridView1.DataBind();
}
}
DataSet虽然很强大,而且是离线数据源,但是需要额外的资源,为了创建更快速的记录集,我们可以用SqlDataReader对象实现相同的效果,但是DataReader相对于DataSet,只能向前。page_load部分的代码如下:
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class clerklist : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//创建连接字符串
string conn_string = System.Configuration.ConfigurationManager.ConnectionStrings["CAROAConnectionString"].ConnectionString;
//创建命令字符串
string comm_string = "select * from clerk";
//构造SqlDataAdapter对象
SqlDataAdapter dataAdapter = new SqlDataAdapter(comm_string, conn_string);
//创建一个DataSet对象
DataSet dataSet = new DataSet();
//填充DataSet对象
dataAdapter.Fill(dataSet, "Clerk");
//从DataSet中获取DataTable
DataTable dataTable = dataSet.Tables["Clerk"];
//将DataTable绑定到GridView
GridView1.DataSource = dataTable;
GridView1.DataBind();
}
}
protected
void
Page_Load(
object
sender, EventArgs e)
{
//创建连接字符串
string conn_string = System.Configuration.ConfigurationManager.ConnectionStrings["CAROAConnectionString"].ConnectionString;
//创建命令字符串
string comm_string = "select * from clerk";
//创建连接对象
SqlConnection conn = new SqlConnection(conn_string);
//创建命令对象
SqlCommand cmd = new SqlCommand(comm_string);
//打开连接
try {
//打开连接
conn.Open();
//为命令对象附加连接
cmd.Connection = conn;
//创建DataReader
SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
GridView1.DataSource = dr;
GridView1.DataBind();
}
finally {
conn.Close();
}
{
//创建连接字符串
string conn_string = System.Configuration.ConfigurationManager.ConnectionStrings["CAROAConnectionString"].ConnectionString;
//创建命令字符串
string comm_string = "select * from clerk";
//创建连接对象
SqlConnection conn = new SqlConnection(conn_string);
//创建命令对象
SqlCommand cmd = new SqlCommand(comm_string);
//打开连接
try {
//打开连接
conn.Open();
//为命令对象附加连接
cmd.Connection = conn;
//创建DataReader
SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
GridView1.DataSource = dr;
GridView1.DataBind();
}
finally {
conn.Close();
}
两个代码执行的结果相同,都在ClerkList.aspx页面显示了员工列表。
ClerkID | RealName | JobNum | DeptID |
---|---|---|---|
1 | 陈公客 | 1001 | 1 |
2 | 王公客 | 1002 | 1 |
3 | 张大客 | 3001 | 3 |
4 | 李大客 | 3002 | 3 |
如果不用ADO.NET,而使用SQLDataSource来完成这个功能,手工键入代码如下:
using System.Web.Configuration;
protected void Page_Load(object sender, EventArgs e)
{
//取得数据库连接设置
ConnectionStringSettings conn_string = WebConfigurationManager.ConnectionStrings["CAROAConnectionString"];
//建立sql命令
string sql_string = "select * from clerk";
//建立SqlDataSource
SqlDataSource sqldsClerkList = new SqlDataSource(conn_string.ConnectionString, sql_string);
//通过SqlDataSource进行查询
DataView dv = (DataView)sqldsClerkList.Select(DataSourceSelectArguments.Empty);
//
GridView1.DataSource = dv;
GridView1.DataBind();
}
根据圣殿祭司的话,以上代码是正宗ASP.NET2.0百分百之纯正语法,虽然我现在还不太明白dataview,dataset,datareader的区别以及适合在何时使用。
如果使用编写效率更高,手工代码更少的可视化方式编写,步骤如下(在实际编程中,我更多的采用这种方法,但是如果需要更灵活的数据操纵,也可以编写CodeBehind):
在ClerkList.aspx中拖入一个SqlDataSource控件,打开智能标签选择配置数据源,在对话框选择已有的连接CAROAConnectionString,接着设置查询语句或者直接从表中选择所需的字段。按下确定,即创建了数据源SqlDataSource1.
自动生成的代码如下:
<
asp:SqlDataSource ID
=
"
SqlDataSource1
"
runat
=
"
server
"
ConnectionString
=
"
<%$ ConnectionStrings:CAROAConnectionString %>
"
SelectCommand = " SELECT * FROM [Clerk] " ></ asp:SqlDataSource >
SelectCommand = " SELECT * FROM [Clerk] " ></ asp:SqlDataSource >
再拖入一个GridView控件,设置数据源为SqlDataSource1,一旦设置了数据源,控件则会利用数据源返回的字段刷新自身的列。
自动生成的代码如下:
<
asp:GridView ID
=
"
GridView1
"
runat
=
"
server
"
AutoGenerateColumns
=
"
False
"
DataKeyNames
=
"
ClerkID
"
DataSourceID = " SqlDataSource1 " >
< Columns >
< asp:BoundField DataField = " Clerk_ID " HeaderText = " ClerkID " InsertVisible = " False "
ReadOnly = " True " SortExpression = " ClerkID " />
< asp:BoundField DataField = " RealName " HeaderText = " RealName " SortExpression = " RealName " />
< asp:BoundField DataField = " JobNum " HeaderText = " JobNum " SortExpression = " JobNum " />
< asp:BoundField DataField = " DeptID " HeaderText = " DeptID " SortExpression = " DeptID " />
</ Columns >
</ asp:GridView >
如果数据库返回的列不需要做任何格式化,那么就不需要为每个列创建一个BoundField,代码可以进一步简化如下:
DataSourceID = " SqlDataSource1 " >
< Columns >
< asp:BoundField DataField = " Clerk_ID " HeaderText = " ClerkID " InsertVisible = " False "
ReadOnly = " True " SortExpression = " ClerkID " />
< asp:BoundField DataField = " RealName " HeaderText = " RealName " SortExpression = " RealName " />
< asp:BoundField DataField = " JobNum " HeaderText = " JobNum " SortExpression = " JobNum " />
< asp:BoundField DataField = " DeptID " HeaderText = " DeptID " SortExpression = " DeptID " />
</ Columns >
</ asp:GridView >
<
asp:GridView ID
=
"
GridView1
"
runat
=
"
server
"
AutoGenerateColumns
=
"
False
"
DataKeyNames
=
"
ClerkID
"
DataSourceID = " SqlDataSource1 " AutoGenerateColumns = " true " />
DataSourceID = " SqlDataSource1 " AutoGenerateColumns = " true " />
以上两个代码实现的效果完全一样。但是后者无法单独设置各个列标题,也无法选择所需的列。
实际上,在本项目中,访问数据库操作采用了分层的概念。app_code中DAL.cs负责底层的数据库操作,各个对象对应的类,比如Clerk.cs则提供了表示层所需的各种业务逻辑。最简单的情况是这样:
Clerk.cs
using
System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
public class Clerk
{
//该方法返回所有职员列表的Dataset
public DataSet GetAllClerkList()
{
return DAL.ExecuteDataset(DAL.CONN_STRING, CommandType.Text,
"select * from clerk", null);
}
}
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
public class Clerk
{
//该方法返回所有职员列表的Dataset
public DataSet GetAllClerkList()
{
return DAL.ExecuteDataset(DAL.CONN_STRING, CommandType.Text,
"select * from clerk", null);
}
}
前台表示层ClerkList.aspx中拖入一个ObjectDataControl控件,数据源设为业务对象Clerk,数据方法select选择GetAllClerkList(),确定后,再拖一个GridView进来并将之数据源指定为ObjecyDataSource1即可。
采用上面这种方法虽然程序结构上分层了,但是GridView本身内置的Edit,Update方法都无法使用,必须写代码。
下面,我们对返回的员工列表结果做进一步扩展。