打开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方法都无法使用,必须写代码。
下面,我们对返回的员工列表结果做进一步扩展。