关于时间的正则
作者:张礼 日期:2008-10-06
时间的正则形式1:2004-01-01 10:30
^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-)) (20|21|22|23|[0-1]?\d):[0-5]?\d$
时间的正则形式2:2004-01-01 10:30:30
^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-)) (20|21|22|23|[0-1]?\d):[0-5]?\d:[0-5]?\d$
时间的正则形式3:2004-01-01
^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$
javascript时间的正则形式3:2004-01-01
Tags: 正则
网站策划书案例
作者:张礼 日期:2008-08-07
一、建设网站前的市场分析
1、相关行业的市场是怎样的,市场有什么样的特点,是否能够在互联网上开展公司业务。
2、市场主要竞争者分析,竞争对手上网情况及其网站规划、功能作用。
3、公司自身条件分析、公司概况、市场优势,可以利用网站提升哪些竞争力,建设网站的能力(费用、技术、人力等)。
二、建设网站目的及功能定位
1、为什么要建立网站,是为了宣传产品,进行电子商务,还是建立行业性网站?是企业的需要还是市场开拓的延伸?
2、整合公司资源,确定网站功能。根据公司的需要和计划,确定网站的功能:产品宣传型、网上营销型、客户服务型、电子商务型等。
3、根据网站功能,确定网站应达到的目的作用。
4、企业内部网(Intranet)的建设情况和网站的可扩展性。
三、网站技术解决方案
根据网站的功能确定网站技术解决方案。
1、采用自建服务器,还是租用虚拟主机。
2、选择操作系统,用unix,Linux还是Window2000/NT。分析投入成本、功能、开发、稳定性和安全性等。
3、采用系统性的解决方案(如IBM,HP)等公司提供的企业上网方案、电子商务解决方案?还是自己开发。
4、网站安全性措施,防黑、防病毒方案。
5、相关程序开发。如网页程序ASP、JSP、CGI、数据库程序等。
四、网站内容规划
1、根据网站的目的和功能规划网站内容,一般企业网站应包括:公司简介、产品介绍、服务内容、价格信息、联系方式、网上定单等基本内容。
2、电子商务类网站要提供会员注册、详细的商品服务信息、信息搜索查询、定单确认、付款、个人信息保密措施、相关帮助等。
3、如果网站栏目比较多,则考虑采用网站编程专人负责相关内容。 注意:网站内容是网站吸引浏览者最重要的因素,无内容或不实用的信息不会吸引匆匆浏览的访客。可事先对人们希望阅读的信息进行调查,并在网站发布后调查人们对网站内容的满意度,以及时调整网站内容。
五、网页设计
1、网页设计美术设计要求,网页美术设计一般要与企业整体形象一致,要符合CI规范。要注意网页色彩、图片的应用及版面规划,保持网页的整体一致性。
2、在新技术的采用上要考虑主要目标访问群体的分布地域、年龄阶层、网络速度、阅读习惯等。
3、制定网页改版计划,如半年到一年时间进行较大规模改版等。
六、网站维护
1、服务器及相关软硬件的维护,对可能出现的问题进行评估,制定响应时间。
2、数据库维护,有效地利用数据是网站维护的重要内容,因此数据库的维护要受到重视。
3、内容的更新、调整等。
4、制定相关网站维护的规定,将网站维护制度化、规范化。
七、网站测试
网站发布前要进行细致周密的测试,以保证正常浏览和使用。主要测试内容:
1、服务器稳定性、安全性。
2、程序及数据库测试。
3、网页兼容性测试,如浏览器、显示器。
4、根据需要的其他测试。
八、网站发布与推广
1、网站测试后进行发布的公关,广告活动。
2、搜索引掣登记等。
九、网站建设日程表
各项规划任务的开始完成时间,负责人等。
十、费用明细
各项事宜所需费用清单。
以上为网站规划书中应该体现的主要内容,根据不同的需求和建站目的,内容也会在增加或减少。在建设网站之初一定要进行细致的规划,才能达到预期建站目的。
Tags: 策划书
checkbox radio 的JS函数
作者:张礼 日期:2008-08-07
/**
- * 全选的所有指定名称的checkbox
- *@state 全选的checkbox的状态
- *@name 表格中的所有checkbox的名称
- *@author fangtf
- *@type void
- */
- function selectAll(state,name) {
- var ids = document.getElementsByName(name);
- for (var i = 0; i < ids.length; i++)
- {
- ids[i].checked = state;
- }
- }
- /**
- * 全选的所有指定id名称的同名checkbox
- *@state 全选的checkbox的状态
- *@name 表格中的所有checkbox的名称
- *@name 表格中的所有checkbox的id
- *@author fangtf
- *@type void
- */
- function selectAllCheckboxByID(state,name,id) {
- var ids = document.getElementsByName(name);
- for (var i = 0; i < ids.length; i++)
- {
- if(ids[i].id == id)
- {
- ids[i].checked = state;
- }
- }
- }
- /**
- * 全选页面上所有的checkbox
- *@state 全选的checkbox的状态
- *@author fangtf
- *@type void
- */
- function selectAlls(state)
- {
- var inputs = document.getElementsByTagName("input");
- for(var i =0;i
- {
- if(inputs[i].type == "checkbox")
- {
- inputs[i].checked =state;
- }
- }
- }
- /**
- *得到鼠标所单击的行
- *@type Object
- */
- function GetRow(oElem) {
- while (oElem) {
- if (oElem.tagName.toLowerCase() == "tr" && oElem.parentElement.tagName.toLowerCase() == "tbody") {
- return oElem;
- }
- if (oElem.tagName.toLowerCase() == "table" || oElem.tagName.toLowerCase() == "th") {
- return false;
- }
- oElemoElem = oElem.parentElement;
- }
- }
-
<head>
<title>radio js改变字体粗细</title>
</head>
<script language="javascript">
function chanage()
{
var rad=document.getElementsByName("r2");
rad[0].checked=false;
var e=document.all.r.value;
document.all.j.style.fontWeight=e;
}
function chanage2()
{
var rad=document.getElementsByName("r");
rad[0].checked=false;
var e=document.all.r2.value;
document.all.j.style.fontWeight=e;
}
</script>
<body>
<input name="i" value="可以变色吗?谢谢!"/>
<input name="j" value="参造字体" style="font:normal"/><br />
<input name="r" type="radio" onClick="chanage();" value="bold">加粗
<input name="r2" type="radio" onClick="chanage2();" value="normal">普通
</body>
如何用JAVASCRIPT得到RADIO的值
如何用JAVASCRIPT得到RADIO的值
<input name="eachzhao" type="radio" value="1" class="radi"> 字串3以下为引用的内容:
function getRadioValue(radioName){
var obj=document.getElementsByName(radioName);
for(var i=0;i<obj.length;i++){
if(obj[i].checked){
return obj[i].value;
}
}
} 字串9
Tags: js
经典SQL语句集锦(收藏版)
作者:张礼 日期:2008-08-07
下列语句部分是MsSql语句,不可以在access中使用。
SQL分类:
DDL—数据定义语言(Create,Alter,Drop,DECLARE)
DML—数据操纵语言(Select,Delete,Update,Insert)
DCL—数据控制语言(GRANT,REVOKE,COMMIT,ROLLBACK)
首先,简要介绍基础语句:
1、说明:创建数据库
Create DATABASE database-name
2、说明:删除数据库
drop database dbname
3、说明:备份sql server
--- 创建 备份数据的 device
USE master
EXEC sp_addumpdevice 'disk', 'testBack', 'c:\mssql7backup\MyNwind_1.dat'
--- 开始 备份
BACKUP DATABASE pubs TO testBack
4、说明:创建新表
create table tabname(col1 type1 [not null] [primary key],col2 type2 [not null],..)
根据已有的表创建新表:
A:create table tab_new like tab_old (使用旧表创建新表)
B:create table tab_new as select col1,col2… from tab_old definition only
5、说明:删除新表
drop table tabname
6、说明:增加一个列
Alter table tabname add column col type
注:列增加后将不能删除。DB2中列加上后数据类型也不能改变,唯一能改变的是增加varchar类型的长度。
7、说明:添加主键: Alter table tabname add primary key(col)
说明:删除主键: Alter table tabname drop primary key(col)
8、说明:创建索引:create [unique] index idxname on tabname(col….)
删除索引:drop index idxname
注:索引是不可更改的,想更改必须删除重新建。
9、说明:创建视图:create view viewname as select statement
删除视图:drop view viewname
10、说明:几个简单的基本的sql语句
选择:select * from table1 where 范围
插入:insert into table1(field1,field2) values(value1,value2)
删除:delete from table1 where 范围
更新:update table1 set field1=value1 where 范围
查找:select * from table1 where field1 like ’%value1%’ ---like的语法很精妙,查资料!
排序:select * from table1 order by field1,field2 [desc]
总数:select count * as totalcount from table1
求和:select sum(field1) as sumvalue from table1
平均:select avg(field1) as avgvalue from table1
最大:select max(field1) as maxvalue from table1
最小:select min(field1) as minvalue from table1
11、说明:几个高级查询运算词
A: UNION 运算符
UNION 运算符通过组合其他两个结果表(例如 TABLE1 和 TABLE2)并消去表中任何重复行而派生出一个结果表。当 ALL 随 UNION 一起使用时(即 UNION ALL),不消除重复行。两种情况下,派生表的每一行不是来自 TABLE1 就是来自 TABLE2。
B: EXCEPT 运算符
EXCEPT 运算符通过包括所有在 TABLE1 中但不在 TABLE2 中的行并消除所有重复行而派生出一个结果表。当 ALL 随 EXCEPT 一起使用时 (EXCEPT ALL),不消除重复行。
C: INTERSECT 运算符
INTERSECT 运算符通过只包括 TABLE1 和 TABLE2 中都有的行并消除所有重复行而派生出一个结果表。当 ALL 随 INTERSECT 一起使用时 (INTERSECT ALL),不消除重复行。
注:使用运算词的几个查询结果行必须是一致的。
12、说明:使用外连接
A、left outer join:
左外连接(左连接):结果集几包括连接表的匹配行,也包括左连接表的所有行。
SQL: select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
B:right outer join:
右外连接(右连接):结果集既包括连接表的匹配连接行,也包括右连接表的所有行。
C:full outer join:
全外连接:不仅包括符号连接表的匹配行,还包括两个连接表中的所有记录。
其次,大家来看一些不错的sql语句
1、说明:复制表(只复制结构,源表名:a 新表名:b) (Access可用)
法一:select * into b from a where 1<>1
法二:select top 0 * into b from a
2、说明:拷贝表(拷贝数据,源表名:a 目标表名:b) (Access可用)
insert into b(a, b, c) select d,e,f from b;
3、说明:跨数据库之间表的拷贝(具体数据使用绝对路径) (Access可用)
insert into b(a, b, c) select d,e,f from b in ‘具体数据库’ where 条件
例子:..from b in '"&Server.MapPath(".")&"\data.mdb" &"' where..
4、说明:子查询(表名1:a 表名2:b)
select a,b,c from a where a IN (select d from b ) 或者: select a,b,c from a where a IN (1,2,3)
5、说明:显示文章、提交人和最后回复时间
select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b
6、说明:外连接查询(表名1:a 表名2:b)
select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
7、说明:在线视图查询(表名1:a )
select * from (Select a,b,c FROM a) T where t.a > 1;
8、说明:between的用法,between限制查询数据范围时包括了边界值,not between不包括
select * from table1 where time between time1 and time2
select a,b,c, from table1 where a not between 数值1 and 数值2
9、说明:in 的使用方法
select * from table1 where a [not] in (‘值1’,’值2’,’值4’,’值6’)
10、说明:两张关联表,删除主表中已经在副表中没有的信息
delete from table1 where not exists ( select * from table2 where table1.field1=table2.field1 )
11、说明:四表联查问题:
select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where .....
12、说明:日程安排提前五分钟提醒
SQL: select * from 日程安排 where datediff('minute',f开始时间,getdate())>5
13、说明:一条sql 语句搞定数据库分页
select top 10 b.* from (select top 20 主键字段,排序字段 from 表名 order by 排序字段 desc) a,表名 b where b.主键字段 = a.主键字段 order by a.排序字段
14、说明:前10条记录
select top 10 * form table1 where 范围
15、说明:选择在每一组b值相同的数据中对应的a最大的记录的所有信息(类似这样的用法可以用于论坛每月排行榜,每月热销产品分析,按科目成绩排名,等等.)
select a,b,c from tablename ta where a=(select max(a) from tablename tb where tb.b=ta.b)
16、说明:包括所有在 TableA 中但不在 TableB和TableC 中的行并消除所有重复行而派生出一个结果表
(select a from tableA ) except (select a from tableB) except (select a from tableC)
17、说明:随机取出10条数据
select top 10 * from tablename order by newid()
18、说明:随机选择记录
select newid()
19、说明:删除重复记录
Delete from tablename where id not in (select max(id) from tablename group by col1,col2,...)
20、说明:列出数据库里所有的表名
select name from sysobjects where type='U'
21、说明:列出表里的所有的
select name from syscolumns where id=object_id('TableName')
22、说明:列示type、vender、pcs字段,以type字段排列,case可以方便地实现多重选择,类似select 中的case。
select type,sum(case vender when 'A' then pcs else 0 end),sum(case vender when 'C' then pcs else 0 end),sum(case vender when 'B' then pcs else 0 end) FROM tablename group by type
显示结果:
type vender pcs
电脑 A 1
电脑 A 1
光盘 B 2
光盘 A 2
手机 B 3
手机 C 3
23、说明:初始化表table1
TRUNCATE TABLE table1
24、说明:选择从10到15的记录
select top 5 * from (select top 15 * from table order by id asc) table_别名 order by id desc
随机选择数据库记录的方法(使用Randomize函数,通过SQL语句实现)
对存储在数据库中的数据来说,随机数特性能给出上面的效果,但它们可能太慢了些。你不能要求ASP“找个随机数”然后打印出来。实际上常见的解决方案是建立如下所示的循环:
Randomize
RNumber = Int(Rnd*499) +1
While Not objRec.EOF
If objRec("ID") = RNumber THEN
... 这里是执行脚本 ...
end if
objRec.MoveNext
Wend
这很容易理解。首先,你取出1到500范围之内的一个随机数(假设500就是数据库内记录的总数)。然后,你遍历每一记录来测试ID 的值、检查其是否匹配RNumber。满足条件的话就执行由THEN 关键字开始的那一块代码。假如你的RNumber 等于495,那么要循环一遍数据库花的时间可就长了。虽然500这个数字看起来大了些,但相比更为稳固的企业解决方案这还是个小型数据库了,后者通常在一个数据库内就包含了成千上万条记录。这时候不就死定了?
采用SQL,你就可以很快地找出准确的记录并且打开一个只包含该记录的recordset,如下所示:
Randomize
RNumber = Int(Rnd*499) + 1
SQL = "Select * FROM Customers Where ID = " & RNumber
set objRec = ObjConn.Execute(SQL)
Response.WriteRNumber & " = " & objRec("ID") & " " & objRec("c_email")
不必写出RNumber 和ID,你只需要检查匹配情况即可。只要你对以上代码的工作满意,你自可按需操作“随机”记录。Recordset没有包含其他内容,因此你很快就能找到你需要的记录这样就大大降低了处理时间。
再谈随机数
现在你下定决心要榨干Random 函数的最后一滴油,那么你可能会一次取出多条随机记录或者想采用一定随机范围内的记录。把上面的标准Random 示例扩展一下就可以用SQL应对上面两种情况了。
为了取出几条随机选择的记录并存放在同一recordset内,你可以存储三个随机数,然后查询数据库获得匹配这些数字的记录:
SQL = "Select * FROM Customers Where ID = " & RNumber & " or ID = " & RNumber2 & " or ID = " & RNumber3
假如你想选出10条记录(也许是每次页面装载时的10条链接的列表),你可以用BETWEEN 或者数学等式选出第一条记录和适当数量的递增记录。这一操作可以通过好几种方式来完成,但是 Select 语句只显示一种可能(这里的ID 是自动生成的号码):
SQL = "Select * FROM Customers Where ID BETWEEN " & RNumber & " AND " & RNumber & "+ 9"
注意:以上代码的执行目的不是检查数据库内是否有9条并发记录。
随机读取若干条记录,测试过
Access语法:Select top 10 * From 表名 orDER BY Rnd(id)
Sql server语法:select top n * from 表名 order by newid()
MySql语法:Select * From 表名 order By rand() Limit n
Access左连接语法(最近开发要用左连接,Access帮助什么都没有,网上没有Access的SQL说明,只有自己测试, 现在记下以备后查)
语法:Select table1.fd1,table1,fd2,table2.fd2 From table1 left join table2 on table1.fd1,table2.fd1 where ...
使用SQL语句 用...代替过长的字符串显示
语法:
SQL数据库:select case when len(field)>10 then left(field,10)+'...' else field end as news_name,news_id from tablename
Access数据库:Select iif(len(field)>2,left(field,2)+'...',field) FROM tablename;
Conn.Execute说明
Execute方法
该方法用于执行SQL语句。根据SQL语句执行后是否返回记录集,该方法的使用格式分为以下两种:
1.执行SQL查询语句时,将返回查询得到的记录集。用法为:
Set 对象变量名=连接对象.Execute("SQL 查询语言")
Execute方法调用后,会自动创建记录集对象,并将查询结果存储在该记录对象中,通过Set方法,将记录集赋给指定的对象保存,以后对象变量就代表了该记录集对象。
2.执行SQL的操作性语言时,没有记录集的返回。此时用法为:
连接对象.Execute "SQL 操作性语句" [, RecordAffected][, Option]
·RecordAffected 为可选项,此出可放置一个变量,SQL语句执行后,所生效的记录数会自动保存到该变量中。通过访问该变量,就可知道SQL语句队多少条记录进行了操作。
·Option 可选项,该参数的取值通常为adCMDText,它用于告诉ADO,应该将Execute方法之后的第一个字符解释为命令文本。通过指定该参数,可使执行更高效。
·BeginTrans、RollbackTrans、CommitTrans方法
这三个方法是连接对象提供的用于事务处理的方法。BeginTrans用于开始一个事物;RollbackTrans用于回滚事务;CommitTrans用于提交所有的事务处理结果,即确认事务的处理。
事务处理可以将一组操作视为一个整体,只有全部语句都成功执行后,事务处理才算成功;若其中有一个语句执行失败,则整个处理就算失败,并恢复到处里前的状态。
BeginTrans和CommitTrans用于标记事务的开始和结束,在这两个之间的语句,就是作为事务处理的语句。判断事务处理是否成功,可通过连接对象的Error集合来实现,若Error集合的成员个数不为0,则说明有错误发生,事务处理失败。Error集合中的每一个Error对象,代表一个错误信息。
ASP.NET中用户不可重复登录
作者:张礼 日期:2008-08-07
ASP.NET中用户不可重复登录
2008-06-05
功能描述:A用户使用AID登录 ,B用户在A用户未退出的情况下也使用AID登录 这时A用户被取消权限
在Global.asax中添加以下代码:
COLOR: blue" twffan="done"> void Application_AcquireRequestState(object sender, EventArgs e)
{
if (Request["MyCookies"] != null && Session["ID"] != null)
{
HttpCookie cookie = Request.Cookies["MyCookies"];
if (cookie[Session["ID"].ToString()] != null)
{
if (Application[Session["ID"].ToString()].ToString() != cookie[Session["ID"].ToString()].ToString())
{
TimeSpan ts = new TimeSpan(-1, 0, 0, 0);
cookie.Expires = DateTime.Now.Add(ts);
Response.AppendCookie(cookie);
Session["ID"] = null;
Request.Cookies.Remove("MyCookies");
}
}
}
} 在需要权限验证的页面(等入窗口)
protected void Button1_Click(object sender, EventArgs e)
{
if (Request.Cookies["MyCookies"] != null)
{
if (Session["ID"] != null)
{
if (Session["ID"].ToString() != this.TextBox1.Text)
{
Res_Cookie();
}
else
{
Response.Write("登录成功!");
}
}
}
else
{
Res_Cookie();
}
}
private void Res_Cookie()
{
string this_time = DateTime.Now.ToString();
Application[this.TextBox1.Text] = this_time;
HttpCookie cookie = new HttpCookie("MyCookies");
TimeSpan ts = new TimeSpan(0, 0, 1, 0);
cookie.Values.Add(this.TextBox1.Text, this_time);
Session["ID"] = this.TextBox1.Text;
Response.AppendCookie(cookie);
Response.Write("登录成功!");
}
在添加个测试按钮: protected void Button2_Click(object sender, EventArgs e)
{
if (Request.Cookies["MyCookies"] == null)
{
Response.Write("登录失败!");
}
else
{
Response.Write("登录成功!");
}
} 最后在session_end事件中对Application中的数据进行释放
Tags: .NET
ASP.NET编程中常用到的27个函数集
作者:张礼 日期:2008-08-07
ASP.NET编程中常用到的27个函数集
csdn.net
2008-6-4
1、DateTime 数字型
System.DateTime currentTime=new System.DateTime();
1.1 取当前年月日时分秒 currentTime=System.DateTime.Now;
1.2 取当前年 int 年=currentTime.Year;
1.3 取当前月 int 月=currentTime.Month;
1.4 取当前日 int 日=currentTime.Day;
1.5 取当前时 int 时=currentTime.Hour;
1.6 取当前分 int 分=currentTime.Minute;
1.7 取当前秒 int 秒=currentTime.Second;
1.8 取当前毫秒 int 毫秒=currentTime.Millisecond;
(变量可用中文)
2、Int32.Parse(变量) Int32.Parse("常量")
字符型转换 转为32位数字型
3、 变量.ToString()
字符型转换 转为字符串
12345.ToString("n"); //生成 12,345.00
12345.ToString("C"); //生成 ¥12,345.00
12345.ToString("e"); //生成 1.234500e+004
12345.ToString("f4"); //生成 12345.0000
12345.ToString("x"); //生成 3039 (16进制)
12345.ToString("p"); //生成 1,234,500.00%
Tags: .NET
决定何时使用 DataGrid、DataList 或 Repeater
作者:张礼 日期:2008-08-07
摘要:了解 ASP.NET 用于显示数据的三个控件: DataGrid、DataList 和 Repeater。 这些控件中的每一个都有独特的特性以及相关的优点和缺点。 创建显示数据的 ASP.NET 应用程序时,为这项工作选择正确的控件非常重要。 正如将在本文中所看到的一样,选择使用 DataGrid、DataList 还是 Repeater,要权衡下面三个因素: 可用性、开发时间和性能。 (12 页打印页)
下载 DataControlsPerfTest_Setup.msi。
本页内容
简介
数据 Web 控件之间的相似性
研究 DataGrid Web 控件
分析 DataList
深入研究 Repeater
小结
基准设置
简介
自从出现了像 Microsoft Active Server Pages (ASP) 这样的简单且基于脚本的 Web 编程技术以来,Web 开发又有了很大的发展。 传统 ASP 中常见的大量枯燥、重复的编码工作,在 Microsoft ASP.NET 中不复存在了。 例如,正如所有传统 ASP 开发人员一度都知道的那样,在传统 ASP Web 页面中显示数据需要下面的伪代码:
Create connection to the databasePopulate an ADO Recordset with a SQL queryDisplay any header HTML neededFor Each Record in the Recordset Print out the Recordset field(s) and associated HTML Move to the next recordNextDisplay any footer HTML needed
例如,要在 HTML <table> 中显示记录集的内容,开发人员则不得不为 <table> 标记 (tag) 生成 HTML 标记 (markup),然后循环遍历记录集中的每一条记录,每次循环生成一个 <tr> 标记,以及许多 <td> 标记和要显示的记录集字段的值。 最后,在循环之后,开发人员需要生成结束 <table> 标记。
传统 ASP 所要求的这种方法有一个很大的缺点: 它把 HTML 内容和 ASP Web 页面的源代码紧密集成在一起。 因为没有分离代码和 HTML 内容,所以更改 HTML 的内容及其困难,尤其是对不懂编程技术的图形艺术家或 Web 设计者来说更是如此。 而且,因为检索数据库结果和生成它的内容都需要代码,所以代码和 HTML 内容的这种集成相对来说需要大量的代码。
幸好,ASP.NET 提供了三个控件,使得在 ASP.NET Web 页面中显示数据绝对比传统 ASP 所需的迭代方式简单得多。 这三个控件是 DataGrid、DataList 和 Repeater,以后我将称之为数据 Web 控件。 也许,如果您已经开发过 ASP.NET Web 页面,那么至少会对这三个控件中的一个有一些经验。 通常,开发人员从学习 DataGrid 开始,这是因为 DataGrid 使用简单以及它具有允许数据排序、分页和编辑的功能。 但是,在 ASP.NET Web 页面中显示数据时,DataGrid 并不总是控件的最佳选择。
在本文中,我们将研究这些数据 Web 控件中每个控件的独特特性。 这些特性赋予每个数据 Web 控件许多优点和缺点。 因为每一个数据 Web 控件都有一些缺点,所以没有可用于任何作业的“完美”控件。 决定使用哪个控件时,必须权衡这三个数据 Web 控件每一个的优点和缺点,然后再决定哪个控件是最合适的。
为了协助进行比较,研究每一个数据 Web 控件时,我们将着重于这三个衡量标准: 可用性(从 Web 访问者的角度)、开发时间和性能。 我们首先快速浏览一下这三个数据 Web 控件之间的相似性。 接下来我们将深入研究 DataGrid,然后研究 DataList,最后查看 Repeater。 对于每一个控件,我们将研究这些控件的功能,并讨论它的功能集是如何影响这些衡量标准的。
返回页首
数据 Web 控件之间的相似性
在研究数据 Web 控件之间的差异(这些差异使它们区别于其他控件)之前,先看一下它们的相似性。 从较高级别观点来看,最基本的相似性是,DataGrid、DataList 和 Repeater都设计为了执行大致相同的操作: 显示数据。 另一个相似性把数据绑定到数据 Web 控件所需的代码。 具体地说,只需要下面两行代码:
dataWebControlID.DataSource = someDataSourcedataWebControlID.DataBind()
通常,赋给数据 Web 控件的 DataSource 属性的 someDataSource 对象是一个 DataSet、SqlDataReader、OleDbDataReader 或一个集合(如 Array、ArrayList 或 System.Collections 命名空间中的其他某个类)。 但是,任何实现 IEnumerable 接口的对象都可以绑定到数据 Web 控件。
DataBind() 方法枚举指定的 DataSource 中的记录。 对于 DataSource 中的每一条记录,都会创建一个项并追加到数据 Web 控件的 Items 集合中。 数据 Web 控件中的每一项都是一个类实例。 用于控件每一项的特定类取决于该数据 Web 控件。 例如,DataGrid 中的每一项都是 DataGridItem 类的一个实例,而 Repeater 中的每一项都是 RepeaterItem 类的一个实例。
每个数据 Web 控件会为它的每一项使用不同的类,因为是这些项呈现的方式决定了数据 Web 控件生成的 HTML 标记。 例如,DataGridItem 类是从 TableRow 类中派生的,这意味着每个 DataGridItem 都或多或少地呈现为一个表行。 这很有意义,因为 DataGrid 设计为在 HTML <table> 标记内以表格形式显示数据,在 HTML <table> 中,每一项都呈现为单独一行。 另一方面,Repeater 设计为允许对它的输出进行完全自定义。 因此,RepeaterItem 类不从 TableRow 类中派生并不令人惊讶。
数据 Web 控件之间的另一个相似性是每个控件都能使用模板提供高度自定义的输出。 DataList 和 Repeater 控件必须 使用模板指定它们的内容,而 DataGrid 则通过 TemplateColumn 列类型可以为特定的列选择使用模板(我们将在下一节“研究 DataGrid Web 控件”中讨论各种不同的 DataGrid 列类型)。
最后一个值得注意的是 DataGrid 和 DataList 控件是从 WebControl 类中派生的,而 Repeater 控件是从 Control 类中派生的。 WebControl 类包含许多美学方面的属性,例如 BackColor、ForeColor、CssClass、BorderStyle 等。 这意味着如果使用 DataGrid 和 DataList,就可以通过它们从 WebControl 类中继承的属性指定样式设置。 而 Repeater 没有任何这样的样式属性。 正如我们将在“深入研究 Repeater”一节中所讨论的一样,对 Repeater 输出的任何可视设置都必须在 Repeater 的模板中指定。
返回页首
研究 DataGrid Web 控件
DataGrid Web 控件是这三个数据 Web 控件中功能最多的,但是在自定义控件生成的实际 HTML 标记时,它又是最不灵活的。 呈现的 HTML 标记中的这种不灵活性,是由于 DataGrid 是设计用于使用 HTML <table> 以表格形式显示数据所造成的。 因此,对于每一条绑定到 DataGrid 的记录,都会创建一个单独的表行(<tr>),对于要显示的记录中的每一个字段,都会创建一个单独的表列(<td>)。
DataGrid 提供了许多功能,可极大地提高要显示的数据的可用性。 例如,把 DataGrid 的 AllowSorting 属性设置为 True 并添加一点源代码,开发人员就可以把一个普通的 DataGrid 变成一个其数据可以由最终用户排序的 DataGrid。 另外,再增加一点工作量,开发人员就能增强 DataGrid 的功能以允许数据分页或数据的内联编辑。 这些功能明显增强了 DataGrid 的可用性。
除了在可用性方面得分很高,DataGrid 还提供了很短的开发时间。 要使用 DataGrid 开始在 ASP.NET Web 页面中显示数据,只需要把 DataGrid 添加到 Web 页面中并编写两行必要的代码: 第一行把数据绑定到 DataGrid 的 DataSource,第二行调用 DataGrid 的 DataBind() 方法。 显然,随着添加到 DataGrid 中的功能数量的增加,开发时间也增加了,但这只是把开发时间和其他数据 Web 控件进行比较。 假设您要允许对 Repeater 显示的数据进行排序。 添加这样的功能是一定可能的,但是与用 DataGrid 完成同样的操作相比,这需要明显多很多的时间和精力。
尽管 DataGrid 具有良好的可用性和开发时间得分,但是这个控件有两个固有的缺点。 第一,正如前面所谈到的,DataGrid 在对所呈现的 HTML 标记进行自定义方面的功能很有限。 是的,您可以自定义 DataGrid 的不同行和列的字体、颜色和边框,但是事实仍然是,当 DataGrid 显示数据时,结果将是一个 HTML <table>,DataSource 中的每一条记录都对应其中一个 <tr>,每一个字段都对应其中一个 <td>。
具体地说,DataGrid 中的每一列都是一个从 DataGridColumn 类中派生的类实例。 有五个内置的 DataGrid 列类型:
? BoundColumn
? ButtonColumn
? EditColumn
? HyperLinkColumn
? TemplateColumn
每一个列类型都提供数据或提供某种允许用户和 DataGrid 进行交互的接口。 例如,BoundColumn 以纯文本显示 DataSource 字段的值,而 HyperLinkColumn 则会显示一个超级链接,其文字和 URL 部分可能是 DataSource 字段。 除了这些内置的列类型,通过创建 DataGridColumn 类的派生类,还可以创建自定义 DataGrid 列类型。 (有关创建一个用于扩展 BoundColumn 功能以限制显示字符数的列的示例,请参阅 Creating a Custom DataGridColumn Class。)
有了这么多的 DataGrid 列类型,可能就不理解为什么 DataGrid 呈现的 HTML 标记不能进行高度自定义了。 要知道,虽然每一个 DataGrid 列类型在呈现时生成不同的 HTML,但是每一列都包含在一组 <td> 标记中,每一行都包含在一组 <tr> 标记中。 因此,即使可以用 TemplateColumn 自定义每一行的特定列的 HTML 输出,而 DataGrid 仍然呈现为 HTML <table>,其中每一行使用一个 <tr>,每一列使用一个 <td> 。 DataGrid 的这种限制禁止了更多具有创造性的数据显示。 例如,如果要在每一表行中显示五条记录,就不能使用 DataGrid,必须使用DataList 或 Repeater。 另外,如果要在除 <table> 之外的 HTML 标记中显示数据,很遗憾,就不能使用 DataGrid 了。
DataGrid 第二个缺点是它的性能。 DataGrid 是这三个数据 Web 控件中性能最差的。 基于这一点,由 DataGrid - 特别是具有许多行的 DataGrids - 产生的 ViewState 可能会非常大。 如果使用 DataGrid 仅仅是为了显示数据,则可以关闭 ViewState,但是,使用 DataGrid 的排序、分页或编辑功能时,就不能这样做了。
为了测试 DataGrid 的性能,我使用了 Microsoft 的免费 Web Application Stress Tool (WAST)。 在本文最后的“基准设置”一节中列出了精确的测试条件和 WAST 设置。 另外,测试使用的代码也可在本文最后下载。
这个 Web Application Stress Tool 会向 Web 服务器发出一组特定的 URL 请求。 对于每一项测试,我都在一分钟之内尽可能快地不断请求一个 URL。 WAST 报告了许多性能衡量标准;我要关注的一个衡量标准是每秒请求数,它表明了 Web 服务器每秒能执行多少次 ASP.NET Web 页面。
对于一个仅显示数据的简单 DataGrid,运行了两个测试。 具体地说,DataGrid 显示了来自 Northwinds 数据库的 Customers 表(Customers 表总共包含 91 条记录)的四个字段。 DataGrid 的 AutoGenerateColumns 属性设置为 True。 第一项测试把 DataGrid 放在一个 Web 窗体( <form runat="server">)中,而第二项测试则没有。 如果在窗体中放置一个控件而不把它的 EnableViewState 属性显式设置为 False,那么该控件则会用 ViewState 保持它的状态。 创建这个 ViewState 项可能是一个比较费时的过程,因此减少了可处理的总的每秒请求数,结果如图 1 所示。
正如我们将要在研究 DataList 和 Repeater 时看到的一样,这两个控件都提供了比 DataGrid 更好的性能。
返回页首
分析 DataList
记得 DataGrid 将呈现为 HTML <table>,每一个 DataSource 记录作为一个表行(<tr>),每一个记录字段作为一个表列(<td>)。 有时,您可能想更多地控制数据的显示。 例如,您可能想把数据显示在 HTML <table> 中,但不是每行显示一条记录,而是每行显示五条记录。 或者,您根本不想把数据显示在 <table> 标记中,而是想把每个元素显示在一个 <span> 标记中。DataList 放弃了 DataGrid 所采用的“列”概念。 相反,DataList 的显示是通过模板 定义的。 利用模板,开发人员可以指定混合的 HTML 语法和数据绑定语法。 HTML 语法是标准的 HTML 标记;数据绑定语法是使用 <%# 和 %> 标记分隔的,用于从 DataSource 的记录中产生用于构造给定 DataList 项的内容。 例如,下面的 ItemTemplate 将显示 DataSource 的字段 CompanyName:
<asp:DataList runat="server" id="myDataList"> <ItemTemplate> <%# DataBinder.Eval(Container.DataItem, "CompanyName") %> </ItemTemplate></asp:DataList>
除了数据绑定语法,模板也可以包含 HTML 标记。 通过更新上面的模板,可以使 CompanyName 字段以粗体显示,而使 ContactName 字段以非粗体显示在 CompanyName 字段的下面:
<asp:DataList runat="server" id="myDataList"> <ItemTemplate> <b><%# DataBinder.Eval(Container.DataItem, "CompanyName") %></b> <br /> <%# DataBinder.Eval(Container.DataItem, "ContactName") %> </ItemTemplate></asp:DataList>
对于 DataList 的 DataSource 中的每一条记录,都要计算 ItemTemplate 的数据绑定语法。 数据绑定语法的输出与 HTML 标记一起指定了为 DataList 项呈现的 HTML。 DataList 还支持其他六个模板,包括 ItemTemplate在内共有如下七个: ? AlternatingItemTemplate
? EditItemTemplate
? FooterTemplate
? HeaderTemplate
? ItemTemplate
? SelectedItemTemplate
? SeparatorTemplate
注意,DataGrid 的 TemplateColumn 仅支持四个模板: ItemTemplate、HeaderTemplate、FooterTemplate 和 EditItemTemplate。默认情况下,DataList 将每一项都显示为 HTML <table> 中的一行。 但是,通过设置 RepeatColumns 属性,您可以指定表的每一行显示多少个 DataList 项。 除了可以指定 HTML <table> 的每一行显示多少个 DataList 项之外,还可以指定 DataList 的内容应该使用 <span> 标记显示,而不是使用 <table> 标记。 DataList 的 RepeatLayout 属性可以设置为 Table 或 Flow,表示 DataList 中的数据呈现在 HTML <table> 中还是 <span> 标记中。利用模板以及 RepeatColumns 和 RepeatLayout 属性,很明显 DataList 比 DataGrid 允许对呈现的 HTML 标记进行更多的自定义。 这种增强了的自定义使得使用 DataList 能够产生更为友好的数据显示,因为 DataGrid 的“每一条 DataSource 记录占用一个表行的单 HTML <table>”模型不可能总是用于显示信息的最佳选择。 但是,只研究比 DataGrid 改进了的自定义并不足以确定 DataList 的可用性;我们还必须比较 DataGrid 和 DataList 的排序、分页和编辑功能。 使用 EditItemIndex 模板以及 EditCommand、UpdateCommand 和 CancelCommand 事件,DataList 可以支持内联编辑。 但是,用 DataList 添加这样的功能比用 DataGrid 花费的开发时间要长。 开发时间的差异是由于下面两个原因: ? 通过 EditCommandColumn 列类型即可在 DataGrid 中创建的编辑/更新/取消按钮,必须手动添加到 DataList 中,以及
? DataGrid BoundColumn 列类型自动使用 TextBox Web 控件作为编辑接口,而使用 DataList 时必须通过 EditItemTemplate 为要编辑的项显式指定的编辑接口。
虽然用 DataList 进行内联编辑不是很困难,但是 DataList 的数据排序、分页和编辑却很困难。 虽然一些灵活的编码肯定能完成这样的功能,但是向 DataList 中添加这样的功能将花费相当多的开发时间。 因此,如果最终用户能对数据进行排序和分页是一个必需要求的话,那么最好选择 DataGrid 而不选择 DataList。DataList 的性能比 DataGrid 的性能好,当 DataList 位于 Web 窗体内时这一点更明显。 图 2 显示了 Web Application Stress Tool 在 DataList 上的测试结果。
图 2: DataList 的每秒请求数
正如图 2 中的结果显示的那样,当 DataList 放置在 Web 窗体内时(因此导致该 Web 控件生成它的 ViewState),该 Web 控件要远胜于 DataGrid。
返回页首
深入研究 Repeater
在所有这三个数据 Web 控件中,Repeater Web 控件在呈现的 HTML 里提供了最大的灵活性。 DataGrid 或 DataList 会在预设的 HTML 标记中自动包含开发人员指定的内容。与它们不同的是,Repeater 在呈现的时候将严格生成指定的 HTML 标记。 因此,如果不想用 HTML <table>或者一系列 <span> 标记显示数据,而希望以其他方式显示数据,就必须使用 Repeater 控件。 就像 DataList 一样,使用 Repeater 时要用模板指定标记。 Repeater 包含下列五个模板: ? AlternatingItemTemplate
? FooterTemplate
? HeaderTemplate
? ItemTemplate
? SeparatorTemplate
HeaderTemplate 和 FooterTemplate 指定出现在绑定到 Repeater 的数据之前和之后的 HTML 标记。 AlternatingItemTemplate 和 ItemTemplate 指定用于呈现 Repeater 的 DataSource 中的每条记录的 HTML 标记和数据绑定语法。 例如,假设您要把包含雇员信息的数据集绑定到 Repeater,该数据集的其中一个字段是 EmployeeName。 如果要在 Web 页上以无序列表的形式显示雇员列表,则可以使用如下 Repeater 语法:
<asp:Repeater runat="server" id="rptEmployees"> <HeaderTemplate> <ul> </HeaderTemplate> <ItemTemplate> <li><%# DataBinder.Eval(Container.DataItem, "EmployeeName") %></li> </ItemTemplate> <FooterTemplate> </ul> </FooterTemplate></asp:Repeater>
与 DataGrid 和 DataList 不同,Repeater 类不是从 WebControl 类派生的。 因此,Repeater 缺少 DataGrid 和 DataList 二者共有的样式属性。 这一点归结起来无非是说,如果想对 Repeater 中所显示数据进行格式设置,则必须在 HTML 标记中进行这样的操作。 例如,在上面的例子中,如果想用粗体显示雇员的姓名,则必须更改 ItemTemplate 以包含 HTML 粗体标记,就像下面这样:
<ItemTemplate> <li><b><%# DataBinder.Eval(Container.DataItem, "EmployeeName") %></b></li></ItemTemplate>
然而对于 DataGrid 或 DataList,通过把控件的 ItemStyle-Font-Bold 属性设置为 True,就能用粗体显示文本了。Repeater 缺少样式属性会大大增加开发的时间指标。 例如,假设决定使用 Repeater 显示数据,这些数据需要以粗体、中间对齐且带有特定背景色的特定字体显示。 所有这些都要用几个 HTML 标记指定,这些标记很快就会使 Repeater 的模板变得凌乱不堪。 这种凌乱会使以后对外观进行更改变得困难得多,尤其是当其他人对该项目进行操作时,则不得不查看大量 HTML 语法。 将这一点与为 DataGrid 或 DataList 指定格式进行比较。 对于这两个控件中的任何一个,都可以通过指定 DataGrid 或 DataList 的样式属性来使模板免于凌乱。 此外,可以用一些工具来自动设置 DataGrid 和 DataList 的样式属性,例如 Microsoft Visual Studio .NET 或 ASP.NET Web Matrix。除了延长开发时间之外,Repeater 还缺少有助于支持分页、编辑或数据编辑的内置功能。 由于缺少这些功能支持,Repeater 在可用性的评定中得分很低。 当然,如果 所有您感兴趣的只是显示数据,而不用带任何别致的铃声或口哨声,那么 Repeater 的功能匮乏就不是主要缺点了。 我之所以强调“如果”一词是因为,通常,Web 应用程序一旦进行了部署,用户就会发现他们需要附加的功能,例如排序、分页和编辑。Repeater 有一个弥补性的品质(这并不令人吃惊),那就是性能。 Repeater 的性能比 DataList 的性能稍微好一点,比 DataGrid 的性能要好很多。图 3 显示了Repeater 每秒能处理的请求数,并与 DataGrid 和 DataList 进行了对比。
图 3: Repeater 的每秒请求数
返回页首
小结
在 ASP.NET Web 页面中显示数据时,很多开发人员都选择他们最熟悉的数据 Web 控件,通常是 DataGrid。 但是这样的盲目决定不够明智,因为根本没有通用的“最好的”数据 Web 控件。 决定为给定的 Web 页使用哪个数据 Web 控件时,应该先就以下各种问题自己考虑一下,以确定哪个控件最适合手边的任务。 您想允许用户对数据进行排序吗? 需要把数据用非 HTML <table> 的格式显示吗? 页面会被大量访问吗,因而性能是一个关键的问题吗?因为 DataGrid 能允许最终用户排序、分页和编辑它的数据,所以这三个数据 Web 控件中 DataGrid Web 控件提供了最好的功能集。 因为使用 DataGrid 时只需要把它添加到 Web 页面中并写几行代码,所以 DataGrid 也是最简单易用的数据 Web 控件。 但是,容易使用和强大的功能是要付出代价的,如性能的代价: DataGrid 是三个数据 Web 控件中效率最低的,特别是当把它放置在 Web 窗体中时。通过使用模板,DataList 对显示的数据外观提供了比 DataGrid 更多的控制。 但是,使用模板通常比使用 DataGrid 的列类型需要更多的开发时间 DataList 还支持数据的内联编辑,但是实现起来需要的工作量比 DataGrid 多。 遗憾的是,在 DataList 中提供分页和排序支持不是一件简单的事。 DataList 比 DataGrid 提供了更好的性能,从而弥补了这些缺少的内置功能。最后,Repeater 控件允许对呈现的 HTML 标记进行完整和全面的控制。 对于 Repeater,生成的唯一 HTML 是模板中数据绑定语句的值和模板中指定的 HTML 标记,而不会生成象 DataGrid 和 DataList 那样的“额外”HTML。 由于要求开发人员指定完整生成的 HTML 标记,所以通常 Repeater 需要的开发时间最长。 而且,Repeater 不提供内置编辑、排序或分页支持。 但是,Repeater 的性能确实是这三个数据 Web 控件中最好的。 它的性能可与 DataList 相比,但明显比 DataGrid 好。祝大家编程愉快!
Tags: .NET
Powered By PJBlog3 v2.8.4.136 CopyRight 2005 - 2008, 奥法的博客 xhtml | css
Processed in 0.064453 second(s) , 2 queries , FatMouse SpringBack Design By FatMouse
湘ICP备07001904号



