web开发中常用的、做成cs文件的js代码

web开发中常用的、做成cs文件的js代码

点击前面 + 查看全部代码
2007/7/13

在ASP.Net中两种利用CSS实现多界面的方法

通过使页面动态加载不同CSS实现多界面

方法一:

<%@page language="C#"%>
<%@import namespace="System.Data"%>
<script language="c#" runat="server">
public void page_load(Object obj,EventArgs e)
{
//创建服务器端控件.
//指定的标记"LINK"初始化此类的新实例.
HtmlGenericControl objLink=new HtmlGenericControl("LINK");
objLink.ID=ID;
objLink.Attributes["rel"]="stylesheet";
objLink.Attributes["type"]="text/css";
objLink.Attributes["href"]="portal.css";

//此控件不产生任何可见输出,仅作为其他控件的容器,可在其中添加,插入或移除控件.
MyCSS.Controls.Add(objLink);
}
</script>
<html>
<head>
<title>c#</title>
<asp:placeholder id="MyCSS" runat="server"></asp:placeholder>
</head>
<body bgColor="#ffcc66" style="FONT:9pt">
<form runat="server">

</form>
</body>
</html>


通过动态设置页面所有同类型控件的样式来该变界面:

方法二:

可以通过改变WEB控件的CssClass属性,可方便地设置和修改控件的样式。
但在实际开发过程中,一个个地设置控件的CssClass属性,非常繁琐,所以此思路应用不广.
但下面的代码段演示了一次性改变页面所有同类型控件的样式的方法,可以实现简单的SKIN等功能。

代码如下:

public void page_load(Object obj,EventArgs e)
{
if(!Page.IsPostBack){
//为页面的所有控件设置样式.
SetCSS(Page.Controls);
}
}

private void SetCSS(System.Web.UI.ControlCollection vControls)
{
for(int i=0;i<vControls.Count;i++)
{
System.Web.UI.Control vControl=vControls[i];

//得到控件的类型
//可增加控件类型及相应处理方法
string PType=vControl.GetType().Name;
switch (PType)
{
case "TextBox":
TextBox_CSS ((TextBox) vControl);
break;
case "Button":
//Button_CSS ((Button) vControl);
break;
case "DataGrid":
//DataGrid_CSS ((DataGrid) vControl);
break;
}
if(vControl.Controls.Count>0)
SetCSS(vControl.Controls);
}
}


private void TextBox_CSS(TextBox tb){
tb.CssClass="TextBox_show";
}

<form runat="server">
<asp:textbox id="Search1" runat="server"/>
<asp:textbox id="Search2" CssClass="INPUT" runat="server"/>
</form>
运行后,查看页面源码.可发现文本框的样式已统一修改为"TextBox_show".

转换函数大全

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%


4、变量.Length 数字型
取字串长度:
如: string str="中国";;
int Len = str.Length ;; //Len是自定义变量, str是求测的字串的变量名

5、System.Text.Encoding.Default.GetBytes(变量)
字码转换 转为比特码
如:byte[] bytStr = System.Text.Encoding.Default.GetBytes(str);;
然后可得到比特长度:
len = bytStr.Length;;

6、System.Text.StringBuilder("")
字符串相加,(+号是不是也一样?)
如:System.Text.StringBuilder sb = new System.Text.StringBuilder("");;
sb.Append("中华");;
sb.Append("人民");;
sb.Append("共和国");;

7、变量.Substring(参数1,参数2);;
截取字串的一部分,参数1为左起始位数,参数2为截取几位。
如:string s1 = str.Substring(0,2);;

8、String user_IP=Request.ServerVariables["REMOTE_ADDR"].ToString();;
取远程用户IP地址

9、穿过代理服务器取远程用户真实IP地址:
if(Request.ServerVariables["HTTP_VIA"]!=null){
string user_IP=Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();;
}else{
string user_IP=Request.ServerVariables["REMOTE_ADDR"].ToString();;
}

10、 Session["变量"];;
存取Session值;
如,赋值: Session["username"]="小布什";;

取值: Object objName=Session["username"];;
String strName=objName.ToString();;
清空: Session.RemoveAll();;

11、String str=Request.QueryString["变量"];;
用超链接传送变量。
如在任一页中建超链接:〈a href=Edit.aspx?fbid=23〉点击〈/a〉
在Edit.aspx页中取值:String str=Request.QueryString["fdid"];;

12、DOC对象.CreateElement("新建节点名");;
创建XML文档新节点

13、父节点.AppendChild(子节点);
将新建的子节点加到XML文档父节点下

14、 父节点.RemoveChild(节点);;
删除节点

15、Response
Response.Write("字串");
Response.Write(变量);
向页面输出。

Response.Redirect("URL地址");
跳转到URL指定的页面

16、char.IsWhiteSpce(字串变量,位数)——逻辑型
查指定位置是否空字符;
如:
string str="中国 人民";;
Response.Write(char.IsWhiteSpace(str,2));; //结果为:True, 第一个字符是0位,2是第三个字符。

17、char.IsPunctuation('字符') --逻辑型
查字符是否是标点符号
如:Response.Write(char.IsPunctuation('A'));; //返回:False

18、(int)'字符'
把字符转为数字,查代码点,注意是单引号。
如:
Response.Write((int)'中');; //结果为中字的代码:20013

19、(char)代码
把数字转为字符,查代码代表的字符。
如:
Response.Write((char)22269);; //返回;国”字。

20、 Trim()
清除字串前后空格

21 、字串变量.Replace("子字串","替换为")
字串替换
如:
string str="中国";;
str=str.Replace("国","央");; //将国字换为央字
Response.Write(str);; //输出结果为;中央”

再如:(这个非常实用)

string str="这是〈script〉脚本";;
str=str.Replace("〈","〈font〉〈〈/font〉");; //将左尖括号替换为〈font〉 与 〈 与 〈/font〉 (或换为〈,但估计经XML存诸后,再提出仍会还原)
Response.Write(str);; //显示为:;这是〈script〉脚本”

如果不替换,〈script〉将不显示,如果是一段脚本,将运行;而替换后,脚本将不运行。
这段代码的价值在于:你可以让一个文本中的所有HTML标签失效,全部显示出来,保护你的具有交互性的站点。
具体实现:将你的表单提交按钮脚本加上下面代码:
string strSubmit=label1.Text;; //label1是你让用户提交数据的控件ID。
strSubmit=strSubmit.Replace("〈","〈font〉〈〈/font〉");;
然后保存或输出strSubmit。
用此方法还可以简单实现UBB代码。

22、Math.Max(i,j)
取i与j中的最大值
如 int x=Math.Max(5,10);; // x将取值 10

23、字串对比一般都用: if(str1==str2){ } , 但还有别的方法:

(1)、
string str1;; str2
//语法: str1.EndsWith(str2);; __检测字串str1是否以字串str2结尾,返回布尔值.如:
if(str1.EndsWith(str2)){ Response.Write("字串str1是以"+str2+"结束的");; }

(2)、
//语法:str1.Equals(str2);; __检测字串str1是否与字串str2相等,返回布尔值,用法同上.

(3)、
//语法 Equals(str1,str2);; __检测字串str1是否与字串str2相等,返回布尔值,用法同上.

24、IndexOf() 、LastIndexOf()
查找字串中指定字符或字串首次(最后一次)出现的位置,返回索引值,如:
str1.IndexOf("字"); //查找;字”在str1中的索引值(位置)
str1.IndexOf("字串");//查找;字串”的第一个字符在str1中的索引值(位置)
str1.IndexOf("字串",3,2);//从str1第4个字符起,查找2个字符,查找;字串”的第一个字符在str1中的索引值(位置)

25、Insert()
在字串中指定索引位插入指定字符。如:
str1.Insert(1,"字");;在str1的第二个字符处插入;字”,如果str1="中国",插入后为;中字国”;

26、PadLeft()、PadRight()
在字串左(或右)加空格或指定char字符,使字串达到指定长度,如:
〈%
string str1="中国人";;
str1=str1.PadLeft(10,'1');; //无第二参数为加空格
Response.Write(str1);; //结果为;1111111中国人” , 字串长为10
%〉

27、Remove()
从指定位置开始删除指定数的字符
字串对比一般都用: if(str1==str2){ } , 但还有别的方法:

1、
string str1;; str2
//语法: str1.EndsWith(str2);; __检测字串str1是否以字串str2结尾,返回布尔值.如:
if(str1.EndsWith(str2)){ Response.Write("字串str1是以"+str2+"结束的");; }

2、
//语法:str1.Equals(str2);; __检测字串str1是否与字串str2相等,返回布尔值,用法同上.

3、
//语法 Equals(str1,str2);; __检测字串str1是否与字串str2相等,返回布尔值,用法同上.

IndexOf()
查找字串中指定字符或字串首次出现的位置,返首索引值,如:
str1.IndexOf("字"); //查找;字”在str1中的索引值(位置)
str1.IndexOf("字串");//查找;字串”的第一个字符在str1中的索引值(位置)
str1.IndexOf("字串",3,2);//从str1第4个字符起,查找2个字符,查找;字串”的第一个字符在str1中的索引值(位置)

1.9 取中文日期显示——年月日时分
string strY=currentTime.ToString("f");; //不显示秒

1.10 取中文日期显示_年月
string strYM=currentTime.ToString("y");;

1.11 取中文日期显示_月日
string strMD=currentTime.ToString("m");;

1.12 取当前年月日,格式为:2003-9-23
string strYMD=currentTime.ToString("d");;

1.13 取当前时分,格式为:14:24
string strT=currentTime.ToString("t");;
2007/7/6

转载(正则表达式)

正则表达式用于字符串处理,表单验证等场合,实用高效,但用到时总是不太把握,以致往往要上网查一番。我将一些常用的表达式收藏在这里,作备忘之用。本贴随时会更新。

匹配中文字符的正则表达式: [\u4e00-\u9fa5]

匹配双字节字符(包括汉字在内):[^\x00-\xff]

应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

String.prototype.len=function(){return this.replace([^\x00-\xff]/g,"aa").length;}

匹配空行的正则表达式:\n[\s| ]*\r

匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/

匹配首尾空格的正则表达式:(^\s*)|(\s*$)

String.prototype.trim = function()
{
    return this.replace(/(^\s*)|(\s*$)/g, "");
}

利用正则表达式分解和转换IP地址:

下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的Javascript程序:

function IP2V(ip)
{
 re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g  //匹配IP地址的正则表达式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
 throw new Error("Not a valid IP address!")
}
}

不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:

var ip="10.100.20.168"
ip=ip.split(".")
alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))

匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

匹配网址URL的正则表达式:http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?

利用正则表达式去除字串中重复的字符的算法程序:[注:此程序不正确,原因见本贴回复]

var s="abacabefgeeii"
var s1=s.replace(/(.).*\1/g,"$1")
var re=new RegExp("["+s1+"]","g")
var s2=s.replace(re,"")
alert(s1+s2)  //结果为:abcefgi

我原来在CSDN上发贴寻求一个表达式来实现去除重复字符的方法,最终没有找到,这是我能想到的最简单的实现方法。思路是使用后向引用取出包括重复的字符,再以重复的字符建立第二个表达式,取到不重复的字符,两者串连。这个方法对于字符顺序有要求的字符串可能不适用。

得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1

s="http://www.9499.net/page1.htm"
s=s.replace(/(.*\/){0,}([^\.]+).*/ig,"$2")
alert(s)

利用正则表达式限制网页表单里的文本框输入内容:

正则表达式限制只能输入中文:onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))"

正则表达式限制只能输入全角字符: onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))"

正则表达式限制只能输入数字:onkeyup="value=value.replace(/[^\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

正则表达式限制只能输入数字和英文:onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

正则表达式,相关链接
http://blog.csdn.net/laily/category/19548.aspx
http://blog.csdn.net/laily/archive/2004/06/30/30525.aspx 微软的正则表达式教程(五):选择/编组和后向引用

http://blog.csdn.net/laily/archive/2004/06/30/30522.aspx 微软的正则表达式教程(四):限定符和定位符

http://blog.csdn.net/laily/archive/2004/06/30/30517.aspx 微软的正则表达式教程(三):字符匹配

http://blog.csdn.net/laily/archive/2004/06/30/30514.aspx 微软的正则表达式教程(二):正则表达式语法和优先权顺序

http://blog.csdn.net/laily/archive/2004/06/30/30511.aspx 微软的正则表达式教程(一):正则表达式简介

http://blog.csdn.net/laily/archive/2004/06/30/30360.aspx 小程序大作为:高级查找/替换、正则表达式练习器、Javascript脚本程序调试器

http://blog.csdn.net/laily/archive/2004/06/24/25872.aspx 经典正则表达式

正则表达式,正规表达式,正则表达式匹配,正则表达式语法,模式匹配,正规表达式匹配 javascript正则表达式 ASP正则表达式 ASP.NET正则表达式 C#正则表达式 JSP正则表达式 PHP正则表达式 VB.NET正则表达式 VBSCript正则表达式编程 delphi正则表达式 jscript

 

正则表达式 regular expression
正则表达式 RegExp
模式 pattern
匹配 Match
.NET命名空间: System.Text.RegularExpression

 

补充:
^\d+$  //匹配非负整数(正整数 + 0)
^[0-9]*[1-9][0-9]*$  //匹配正整数
^((-\d+)|(0+))$  //匹配非正整数(负整数 + 0)
^-[0-9]*[1-9][0-9]*$  //匹配负整数
^-?\d+$    //匹配整数
^\d+(\.\d+)?$  //匹配非负浮点数(正浮点数 + 0)
^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$  //匹配正浮点数
^((-\d+(\.\d+)?)|(0+(\.0+)?))$  //匹配非正浮点数(负浮点数 + 0)
^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$  //匹配负浮点数
^(-?\d+)(\.\d+)?$  //匹配浮点数
^[A-Za-z]+$  //匹配由26个英文字母组成的字符串
^[A-Z]+$  //匹配由26个英文字母的大写组成的字符串
^[a-z]+$  //匹配由26个英文字母的小写组成的字符串
^[A-Za-z0-9]+$  //匹配由数字和26个英文字母组成的字符串
^\w+$  //匹配由数字、26个英文字母或者下划线组成的字符串
^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$    //匹配email地址
^[a-zA-z]+://匹配(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$  //匹配url

 

利用正则表达式去除字串中重复的字符的算法程序:

var s="abacabefgeeii"
var s1=s.replace(/(.).*\1/g,"$1")
var re=new RegExp("["+s1+"]","g")
var s2=s.replace(re,"")
alert(s1+s2) //结果为:abcefgi
===============================
如果var s = "abacabefggeeii"
结果就不对了,结果为:abeicfgg
正则表达式的能力有限

 

1.确认有效电子邮件格式
下面的代码示例使用静态 Regex.IsMatch 方法验证一个字符串是否为有效电子邮件格式。如果字符串包含一个有效的电子邮件地址,则 IsValidEmail 方法返回 true,否则返回 false,但不采取其他任何操作。您可以使用 IsValidEmail,在应用程序将地址存储在数据库中或显示在 ASP.NET 页中之前,筛选出包含无效字符的电子邮件地址。

[Visual Basic]
Function IsValidEmail(strIn As String) As Boolean
' Return true if strIn is in valid e-mail format.
Return Regex.IsMatch(strIn, ("^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$")
End Function
[C#]
bool IsValidEmail(string strIn)
{
// Return true if strIn is in valid e-mail format.
return Regex.IsMatch(strIn, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
}


2.清理输入字符串
下面的代码示例使用静态 Regex.Replace 方法从字符串中抽出无效字符。您可以使用这里定义的 CleanInput 方法,清除掉在接受用户输入的窗体的文本字段中输入的可能有害的字符。CleanInput 在清除掉除 @、-(连字符)和 .(句点)以外的所有非字母数字字符后返回一个字符串。

[Visual Basic]
Function CleanInput(strIn As String) As String
' Replace invalid characters with empty strings.
Return Regex.Replace(strIn, "[^\w\.@-]", "")
End Function
[C#]
String CleanInput(string strIn)
{
// Replace invalid characters with empty strings.
return Regex.Replace(strIn, @"[^\w\.@-]", "");
}


3.更改日期格式
以下代码示例使用 Regex.Replace 方法来用 dd-mm-yy 的日期形式代替 mm/dd/yy 的日期形式。

[Visual Basic]
Function MDYToDMY(input As String) As String
Return Regex.Replace(input, _
"\b(?<month>\d{1,2})/(?<day>\d{1,2})/(?<year>\d{2,4})\b", _
"${day}-${month}-${year}")
End Function
[C#]
String MDYToDMY(String input)
{
return Regex.Replace(input,
"\\b(?<month>\\d{1,2})/(?<day>\\d{1,2})/(?<year>\\d{2,4})\\b",
"${day}-${month}-${year}");
}
Regex 替换模式
本示例说明如何在 Regex.Replace 的替换模式中使用命名的反向引用。其中,替换表达式 ${day} 插入由 (?<day>...) 组捕获的子字符串。

有几种静态函数使您可以在使用正则表达式操作时无需创建显式正则表达式对象,而 Regex.Replace 函数正是其中之一。如果您不想保留编译的正则表达式,这将给您带来方便


4.提取 URL 信息
以下代码示例使用 Match.Result 来从 URL 提取协议和端口号。例如,“http://www.contoso.com:8080/letters/readme.html”将返回“http:8080”。

[Visual Basic]
Function Extension(url As String) As String
Dim r As New Regex("^(?<proto>\w+)://[^/]+?(?<port>:\d+)?/", _
RegexOptions.Compiled)
Return r.Match(url).Result("${proto}${port}")
End Function
[C#]
String Extension(String url)
{
Regex r = new Regex(@"^(?<proto>\w+)://[^/]+?(?<port>:\d+)?/",
RegexOptions.Compiled);
return r.Match(url).Result("${proto}${port}");
}

  一、正则表达式基础知识
  我们先从简单的开始。假设你要搜索一个包含字符“cat”的字符串,搜索用的正则表达式就是“cat”。如果搜索对大小写不敏感,单词“catalog”、“Catherine”、“sophisticated”都可以匹配。也就是说:


  1.1句点符号
  假设你在玩英文拼字游戏,想要找出三个字母的单词,而且这些单词必须以“t”字母开头,以“n”字母结束。另外,假设有一本英文字典,你可以用正则表达式搜索它的全部内容。要构造出这个正则表达式,你可以使用一个通配符??句点符号“.”。这样,完整的表达式就是“t.n”,它匹配“tan”、“ten”、“tin”和“ton”,还匹配 “t#n”、“tpn”甚至“tn”,还有其他许多无意义的组合。这是因为句点符号匹配所有字符,包括空格、Tab字符甚至换行符:

  1.2方括号符号
  为了解决句点符号匹配范围过于广泛这一问题,你可以在方括号(“[]”)里面指定看来有意义的字符。此时,只有方括号里面指定的字符才参与匹配。也就是说,正则表达式“t[aeio]n”只匹配“tan”、“Ten”、“tin”和“ton”。但“Toon”不匹配,因为在方括号之内你只能匹配单个字符:

  1.4表示匹配次数的符号
  表一显示了表示匹配次数的符号,这些符号用来确定紧靠该符号左边的符号出现的次数:

  假设我们要在文本文件中搜索美国的社会安全号码。这个号码的格式是999-99-9999。用来匹配它的正则表达式如图一所示。在正则表达式中,连字符(“-”)有着特殊的意义,它表示一个范围,比如从0到9。因此,匹配社会安全号码中的连字符号时,它的前面要加上一个转义字符“\”。

  图一:匹配所有123-12-1234形式的社会安全号码
  假设进行搜索的时候,你希望连字符号可以出现,也可以不出现??即,999-99-9999和999999999都属于正确的格式。这时,你可以在连字符号后面加上“?”数量限定符号,如图二所示:

  图二:匹配所有123-12-1234和123121234形式的社会安全号码
  下面我们再来看另外一个例子。美国汽车牌照的一种格式是四个数字加上二个字母。它的正则表达式前面是数字部分“[0-9]{ 4}”,再加上字母部分“[A-Z]{ 2}”。图三显示了完整的正则表达式

  图三:匹配典型的美国汽车牌照号码,如8836KV
  1.5“否”符号
  “^”符号称为“否”符号。如果用在方括号内,“^”表示不想要匹配的字符。例如,图四的正则表达式匹配所有单词,但以“X”字母开头的单词除外。

  图四:匹配所有单词,但“X”开头的除外
  1.6圆括号和空白符号
  假设要从格式为“June26,1951”的生日日期中提取出月份部分,用来匹配该日期的正则表达式可以如图五所示:

  图五:匹配所有MothDD,YYYY格式的日期
  新出现的“\s”符号是空白符号,匹配所有的空白字符,包括Tab字符。如果字符串正确匹配,接下来如何提取出月份部分呢?只需在月份周围加上一个圆括号创建一个组,然后用OROAPI(本文后面详细讨论)提取出它的值。修改后的正则表达式如图六所示:

  图六:匹配所有MonthDD,YYYY格式的日期,定义月份值为第一个组
  1.7其它符号
  为简便起见,你可以使用一些为常见正则表达式创建的快捷符号。如表二所示:
  表二:常用符号

  例如,在前面社会安全号码的例子中,所有出现“[0-9]”的地方我们都可以使用“\d”。修改后的正则表达式如图七所示:


/*------------------------
功能:替换任何空白字符
-------------------------*/
function TrimString (strVal)
{
strTmp = strVal + "";
if (strTmp.length == 0)
return (strTmp);
reVal = /^\s*/;
strTmp = strTmp.replace (reVal, '');
reVal = /\s*$/;
return (strTmp.replace (reVal, ''));
}

/*------------------------
功能:检测是否是有效数字
-------------------------*/
function Check_Num( num )
{
num = ( TrimString( num ) );
if (num.length == 0)
return (false);
return ( Number( num ) );
}

/*------------------------
功能:检测是否是有效日期
-------------------------*/
function Check_Date (strDate)
{
strDate = (TrimString (strDate));
if (strDate.length == 0)
return (false);
reVal = /^([1-2]\d{3})[\/|\-](0?[1-9]|10|11|12)[\/|\-]([1-2]?[0-9]|0[1-9]|30|31)$/;
return (reVal.test (strDate));
}

/*------------------------
功能:检测是否是有效Email
-------------------------*/
function Check_Email (strEmail)
{
strEmail = (TrimString (strEmail));
if (strEmail.length == 0)
return (false);

reVal = /^[\-!#\$%&'\*\+\\\.\/0-9=\?A-Z\^_`a-z{|}~]+@[\-!#\$%&'\*\+\\\.\/0-9=\?A-Z\^_`a-z{|}~]+(\.[\-!#\$%&'\*\+\\\.\/0-9=\?A-Z\^_`a-z{|}~]+)+$/;
return (reVal.test (strEmail));
}

/*------------------------
功能:检测是否是有效时间
-------------------------*/
function Check_Time (strTime)
{
strTime = (TrimString (strTime));
if (strTime.length == 0)
return (false);

reVal = /^(([0-9]|[01][0-9]|2[0-3])(:([0-9]|[0-5][0-9])){0,2}|(0?[0-9]|1[0-1])(:([0-9]|[0-5][0-9])){0,2}\s?[aApP][mM])?$/;
return (reVal.test (strTime));
}

/*------------------------
功能:检测是否是有效日期特定格式
-------------------------*/
function Check_Date_1 (strDate)
{
strDate = (TrimString (strDate));
if (strDate.length == 0)
return (false);
reVal = /^([1-2]\d{3})[\/](0?[1-9]|10|11|12)[\/]([1-2]?[0-9]|0[1-9]|30|31)$/;
return (reVal.test (strDate));
}

/*------------------------
功能:检测是否是有效日期特定格式
-------------------------*/
function Check_Date_2 (strDate)
{
strDate = (TrimString (strDate));
if (strDate.length == 0)
return (false);
reVal = /^([1-2]\d{3})[\-](0[1-9]|10|11|12)[\-]([1-2][0-9]|0[1-9]|30|31)$/;
return (reVal.test (strDate));
}

/*--------------------------------------
功能:换行定行
---------------------------------------*/
function enter( form, temp )
{
if ( window.event.keyCode == 13 )
{
eval( form + temp + ".focus()" );
eval( form + temp + ".select()" );
}
else
return (false);
}

/*--------------------------------------
功能:检查字符串长度
---------------------------------------*/
function ByteString (strVal)
{
nLen = 0;

for (i = 0; i < strVal.length; i ++)
{
if (strVal.charCodeAt (i) > 255)
nLen += 2;
else
nLen ++;
};
return (nLen);
}

/*--------------------------------------
功能:按要求截取字符串长度
---------------------------------------*/
function SubString(strVal,nStrLen)
{
nLen = 0;
nTemp = 0;
for (i = 0; i < strVal.length; i ++)
{
if (strVal.charCodeAt (i) > 255)
nLen += 2;
else
nLen ++;
if(nLen <= nStrLen)
nTemp = i;
else
break;
};
return(strVal.substr(0,nTemp+1));
}

/*------------------------
功能:检测密码,密码只能由英文字母、数字、减号、下划线、$、#、*、(和)构成,且首位必须是英文字母
-------------------------*/
function Check_Pass( strPass )
{
strPass = ( TrimString( strPass ) );
if (strPass.length == 0)
return (false);
reVal = /^[a-zA-Z]{1}[a-zA-Z0-9-_$#*()]{0,29}$/;
return ( reVal.test (strPass) );
}

这是所有的,不过是PHP的,你自己转换一下吧~~

# re: 正则表达式 2005-02-28 00:59 yongsheng

^(((19)|(20))\d{2})(((((-|/)0?)|0)[1-9])|((-|/)?1[0-2]))((((((-|/)0?)|0)[1-9])|((-|/)?[1-2][0-9]))|((-|/)?3[0-1]))$


2004-1-1格式

# re: 正则表达式 2005-03-07 14:33 yongsheng

一、验证类
1、数字验证内
1.1 整数
1.2 大于0的整数 (用于传来的ID的验证)
1.3 负整数的验证
1.4 整数不能大于iMax
1.5 整数不能小于iMin
2、时间类
2.1 短时间,形如 (13:04:06)
2.2 短日期,形如 (2003-12-05)
2.3 长时间,形如 (2003-12-05 13:04:06)
2.4 只有年和月。形如(2003-05,或者2003-5)
2.5 只有小时和分钟,形如(12:03)
3、表单类
3.1 所有的表单的值都不能为空
3.2 多行文本框的值不能为空。
3.3 多行文本框的值不能超过sMaxStrleng
3.4 多行文本框的值不能少于sMixStrleng
3.5 判断单选框是否选择。
3.6 判断复选框是否选择.
3.7 复选框的全选,多选,全不选,反选
3.8 文件上传过程中判断文件类型
4、字符类
4.1 判断字符全部由a-Z或者是A-Z的字字母组成
4.2 判断字符由字母和数字组成。
4.3 判断字符由字母和数字,下划线,点号组成.且开头的只能是下划线和字母
4.4 字符串替换函数.Replace();
5、浏览器类
5.1 判断浏览器的类型
5.2 判断ie的版本
5.3 判断客户端的分辨率

6、结合类
6.1 email的判断。
6.2 手机号码的验证
6.3 身份证的验证


二、功能类

1、时间与相关控件类
1.1 日历
1.2 时间控件
1.3 万年历
1.4 显示动态显示时钟效果(文本,如OA中时间)
1.5 显示动态显示时钟效果 (图像,像手表)
2、表单类
2.1 自动生成表单
2.2 动态添加,修改,删除下拉框中的元素
2.3 可以输入内容的下拉框
2.4 多行文本框中只能输入iMax文字。如果多输入了,自动减少到iMax个文字(多用于短信发送)

3、打印类
3.1 打印控件
4、事件类
4.1 屏蔽右键
4.2 屏蔽所有功能键
4.3 --> 和<-- F5 F11,F9,F1
4.4 屏蔽组合键ctrl+N
5、网页设计类
5.1 连续滚动的文字,图片(注意是连续的,两段文字和图片中没有空白出现)
5.2 html编辑控件类
5.3 颜色选取框控件
5.4 下拉菜单
5.5 两层或多层次的下拉菜单
5.6 仿IE菜单的按钮。(效果如rongshuxa.com的导航栏目)
5.7 状态栏,title栏的动态效果(例子很多,可以研究一下)
5.8 双击后,网页自动滚屏
6、树型结构。
6.1 asp+SQL版
6.2 asp+xml+sql版
6.3 java+sql或者java+sql+xml
7、无边框效果的制作
8、连动下拉框技术
9、文本排序


一、验证类
1、数字验证内
1.1 整数
/^(-|\+)?\d+$/.test(str)
1.2 大于0的整数 (用于传来的ID的验证)
/^\d+$/.test(str)
1.3 负整数的验证
/^-\d+$/.test(str)
2、时间类
2.1 短时间,形如 (13:04:06)
function isTime(str)
{
var a = str.match(/^(\d{1,2})(:)?(\d{1,2})\2(\d{1,2})$/);
if (a == null) {alert('输入的参数不是时间格式'); return false;}
if (a[1]>24 || a[3]>60 || a[4]>60)
{
alert("时间格式不对");
return false
}
return true;
}
2.2 短日期,形如 (2003-12-05)
function strDateTime(str)
{
var r = str.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/);
if(r==null)return false;
var d= new Date(r[1], r[3]-1, r[4]);
return (d.getFullYear()==r[1]&&(d.getMonth()+1)==r[3]&&d.getDate()==r[4]);
}
2.3 长时间,形如 (2003-12-05 13:04:06)
function strDateTime(str)
{
var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/;
var r = str.match(reg);
if(r==null)return false;
var d= new Date(r[1], r[3]-1,r[4],r[5],r[6],r[7]);
return (d.getFullYear()==r[1]&&(d.getMonth()+1)==r[3]&&d.getDate()==r[4]&&d.getHours()==r[5]&&d.getMinutes()==r[6]&&d.getSeconds()==r[7]);
}
2.4 只有年和月。形如(2003-05,或者2003-5)
2.5 只有小时和分钟,形如(12:03)
3、表单类
3.1 所有的表单的值都不能为空
<input onblur="if(this.value.replace(/^\s+|\s+$/g,'')=='')alert('不能为空!')">
3.2 多行文本框的值不能为空。
3.3 多行文本框的值不能超过sMaxStrleng
3.4 多行文本框的值不能少于sMixStrleng
3.5 判断单选框是否选择。
3.6 判断复选框是否选择.
3.7 复选框的全选,多选,全不选,反选
3.8 文件上传过程中判断文件类型
4、字符类
4.1 判断字符全部由a-Z或者是A-Z的字字母组成
<input onblur="if(/[^a-zA-Z]/g.test(this.value))alert('有错')">
4.2 判断字符由字母和数字组成。
<input onblur="if(/[^0-9a-zA-Z]/g.test(this.value))alert('有错')">
4.3 判断字符由字母和数字,下划线,点号组成.且开头的只能是下划线和字母
/^([a-zA-z_]{1})([\w]*)$/g.test(str)
4.4 字符串替换函数.Replace();
5、浏览器类
5.1 判断浏览器的类型
window.navigator.appName
5.2 判断ie的版本
window.navigator.appVersion
5.3 判断客户端的分辨率
window.screen.height; window.screen.width;

6、结合类
6.1 email的判断。
function ismail(mail)
{
return(new RegExp(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(mail));
}
6.2 手机号码的验证
6.3 身份证的验证
function isIdCardNo(num)
{
if (isNaN(num)) {alert("输入的不是数字!"); return false;}
var len = num.length, re;
if (len == 15)
re = new RegExp(/^(\d{6})()?(\d{2})(\d{2})(\d{2})(\d{3})$/);
else if (len == 18)
re = new RegExp(/^(\d{6})()?(\d{4})(\d{2})(\d{2})(\d{3})(\d)$/);
else {alert("输入的数字位数不对!"); return false;}
var a = num.match(re);
if (a != null)
{
if (len==15)
{
var D = new Date("19"+a[3]+"/"+a[4]+"/"+a[5]);
var B = D.getYear()==a[3]&&(D.getMonth()+1)==a[4]&&D.getDate()==a[5];
}
else
{
var D = new Date(a[3]+"/"+a[4]+"/"+a[5]);
var B = D.getFullYear()==a[3]&&(D.getMonth()+1)==a[4]&&D.getDate()==a[5];
}
if (!B) {alert("输入的身份证号 "+ a[0] +" 里出生日期不对!"); return false;}
}
return true;
}

3.7 复选框的全选,多选,全不选,反选
<form name=hrong>
<input type=checkbox name=All onclick="checkAll('mm')">全选<br/>
<input type=checkbox name=mm onclick="checkItem('All')"><br/>
<input type=checkbox name=mm onclick="checkItem('All')"><br/>
<input type=checkbox name=mm onclick="checkItem('All')"><br/>
<input type=checkbox name=mm onclick="checkItem('All')"><br/>
<input type=checkbox name=mm onclick="checkItem('All')"><br/><br/>


<input type=checkbox name=All2 onclick="checkAll('mm2')">全选<br/>
<input type=checkbox name=mm2 onclick="checkItem('All2')"><br/>
<input type=checkbox name=mm2 onclick="checkItem('All2')"><br/>
<input type=checkbox name=mm2 onclick="checkItem('All2')"><br/>
<input type=checkbox name=mm2 onclick="checkItem('All2')"><br/>
<input type=checkbox name=mm2 onclick="checkItem('All2')"><br/>

</form>

<SCRIPT LANGUAGE="JavaScript">
function checkAll(str)
{
var a = document.getElementsByName(str);
var n = a.length;
for (var i=0; i<n; i++)
a[i].checked = window.event.srcElement.checked;
}
function checkItem(str)
{
var e = window.event.srcElement;
var all = eval("document.hrong."+ str);
if (e.checked)
{
var a = document.getElementsByName(e.name);
all.checked = true;
for (var i=0; i<a.length; i++)
{
if (!a[i].checked){ all.checked = false; break;}
}
}
else all.checked = false;
}
</SCRIPT>

3.8 文件上传过程中判断文件类型
<input type=file onchange="alert(this.value.match(/^(.*)(\.)(.{1,8})$/)[3])">

画图:
<OBJECT
id=S
style="LEFT: 0px; WIDTH: 392px; TOP: 0px; HEIGHT: 240px"
height=240
width=392
classid="clsid:369303C2-D7AC-11D0-89D5-00A0C90833E6">
</OBJECT>
<SCRIPT>
S.DrawingSurface.ArcDegrees(0,0,0,30,50,60);
S.DrawingSurface.ArcRadians(30,0,0,30,50,60);
S.DrawingSurface.Line(10,10,100,100);
</SCRIPT>

写注册表:
<SCRIPT>
var WshShell = WScript.CreateObject("WScript.Shell");
WshShell.RegWrite ("HKCU\\Software\\ACME\\FortuneTeller\\", 1, "REG_BINARY");
WshShell.RegWrite ("HKCU\\Software\\ACME\\FortuneTeller\\MindReader", "Goocher!", "REG_SZ");
var bKey = WshShell.RegRead ("HKCU\\Software\\ACME\\FortuneTeller\\");
WScript.Echo (WshShell.RegRead ("HKCU\\Software\\ACME\\FortuneTeller\\MindReader"));
WshShell.RegDelete ("HKCU\\Software\\ACME\\FortuneTeller\\MindReader");
WshShell.RegDelete ("HKCU\\Software\\ACME\\FortuneTeller\\");
WshShell.RegDelete ("HKCU\\Software\\ACME\\");
</SCRIPT>

TABLAE相关(客户端动态增加行列)
<HTML>
<SCRIPT LANGUAGE="JScript">
function numberCells() {
var count=0;
for (i=0; i < document.all.mytable.rows.length; i++) {
for (j=0; j < document.all.mytable.rows(i).cells.length; j++) {
document.all.mytable.rows(i).cells(j).innerText = count;
count++;
}
}
}
</SCRIPT>
<BODY onload="numberCells()">
<TABLE id=mytable border=1>
<TR><TH>&nbsp;</TH><TH>&nbsp;</TH><TH>&nbsp;</TH><TH>&nbsp;</TH></TR>
<TR><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>
<TR><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>
</TABLE>
</BODY>
</HTML>

1.身份证严格验证:

<script>
var aCity={11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",21:"辽宁",22:"吉林",23:"黑龙江 ",31:"上海",32:"江苏",33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东",41:"河南",42:"湖北 ",43:"湖南",44:"广东",45:"广西",46:"海南",50:"重庆",51:"四川",52:"贵州",53:"云南",54:"西藏 ",61:"陕西",62:"甘肃",63:"青海",64:"宁夏",65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外 "}

function cidInfo(sId){
var iSum=0
var info=""
if(!/^\d{17}(\d|x)$/i.test(sId))return false;
sId=sId.replace(/x$/i,"a");
if(aCity[parseInt(sId.substr(0,2))]==null)return "Error:非法地区";
sBirthday=sId.substr(6,4)+"-"+Number(sId.substr(10,2))+"-"+Number(sId.substr(12,2));
var d=new Date(sBirthday.replace(/-/g,"/"))
if(sBirthday!=(d.getFullYear()+"-"+ (d.getMonth()+1) + "-" + d.getDate()))return "Error:非法生日";
for(var i = 17;i>=0;i --) iSum += (Math.pow(2,i) % 11) * parseInt(sId.charAt(17 - i),11)
if(iSum%11!=1)return "Error:非法证号";
return aCity[parseInt(sId.substr(0,2))]+","+sBirthday+","+(sId.substr(16,1)%2?"男":"女")
}

document.write(cidInfo("380524198002300016"),"<br/>");
document.write(cidInfo("340524198002300019"),"<br/>")
document.write(cidInfo("340524197711111111"),"<br/>")
document.write(cidInfo("34052419800101001x"),"<br/>");
</script>

2.验证IP地址
<SCRIPT LANGUAGE="JavaScript">
function isip(s){
var check=function(v){try{return (v<=255 && v>=0)}catch(x){return false}};
var re=s.split(".")
return (re.length==4)?(check(re[0]) && check(re[1]) && check(re[2]) && check(re[3])):false
}

var s="202.197.78.129";
alert(isip(s))
</SCRIPT>



3.加sp1后还能用的无边框窗口!!
<HTML XMLNS:IE>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<IE:Download ID="include" STYLE="behavior:url(#default#download)" />
<title>Chromeless Window</title>

<SCRIPT LANGUAGE="JScript">
/*--- Special Thanks For andot ---*/

/*
This following code are designed and writen by Windy_sk <seasonx@163.net>
You can use it freely, but u must held all the copyright items!
*/

/*--- Thanks For andot Again ---*/

var CW_width = 400;
var CW_height = 300;
var CW_top = 100;
var CW_left = 100;
var CW_url = "/";
var New_CW = window.createPopup();
var CW_Body = New_CW.document.body;
var content = "";
var CSStext = "margin:1px;color:black; border:2px outset;border-style:expression(onmouseout=onmouseup=function(){this.style.borderStyle='outset'}, onmousedown=function(){if(event.button!=2)this.style.borderStyle='inset'});background-color:buttonface;width:16px;height:14px;font-size:12px;line-height:11px;cursor:Default;";

//Build Window
include.startDownload(CW_url, function(source){content=source});

function insert_content(){
var temp = "";
CW_Body.style.overflow = "hidden";
CW_Body.style.backgroundColor = "white";
CW_Body.style.border = "solid black 1px";
content = content.replace(/<a ([^>]*)>/g,"<a onclick='parent.open(this.href);return false' $1>");
temp += "<table width=100% height=100% cellpadding=0 cellspacing=0 border=0>";
temp += "<tr style=';font-size:12px;background:#0099CC;height:20;cursor:default' ondblclick=\"Max.innerText=Max.innerText=='1'?'2':'1';parent.if_max=!parent.if_max;parent.show_CW();\" onmouseup='parent.drag_up(event)' onmousemove='parent.drag_move(event)' onmousedown='parent.drag_down(event)' onselectstart='return false' oncontextmenu='return false'>";
temp += "<td style='color:#ffffff;padding-left:5px'>Chromeless Window For IE6 SP1</td>";
temp += "<td style='color:#ffffff;padding-right:5px;' align=right>";
temp += "<span id=Help onclick=\"alert('Chromeless Window For IE6 SP1 - Ver 1.0\\n\\nCode By Windy_sk\\n\\nSpecial Thanks For andot')\" style=\""+CSStext+"font-family:System;padding-right:2px;\">?</span>";
temp += "<span id=Min onclick='parent.New_CW.hide();parent.blur()' style=\""+CSStext+"font-family:Webdings;\" title='Minimum'>0</span>";
temp += "<span id=Max onclick=\"this.innerText=this.innerText=='1'?'2':'1';parent.if_max=!parent.if_max;parent.show_CW();\" style=\""+CSStext+"font-family:Webdings;\" title='Maximum'>1</span>";
temp += "<span id=Close onclick='parent.opener=null;parent.close()' style=\""+CSStext+"font-family:System;padding-right:2px;\" title='Close'>x</span>";
temp += "</td></tr><tr><td colspan=2>";
temp += "<div id=include style='overflow:scroll;overflow-x:hidden;overflow-y:auto; HEIGHT: 100%; width:"+CW_width+"'>";
temp += content;
temp += "</div>";
temp += "</td></tr></table>";
CW_Body.innerHTML = temp;
}

setTimeout("insert_content()",1000);

var if_max = true;
function show_CW(){
window.moveTo(10000, 10000);
if(if_max){
New_CW.show(CW_top, CW_left, CW_width, CW_height);
if(typeof(New_CW.document.all.include)!="undefined"){
New_CW.document.all.include.style.width = CW_width;
New_CW.document.all.Max.innerText = "1";
}

}else{
New_CW.show(0, 0, screen.width, screen.height);
New_CW.document.all.include.style.width = screen.width;
}
}

window.onfocus = show_CW;
window.onresize = show_CW;

// Move Window
var drag_x,drag_y,draging=false

function drag_move(e){
if (draging){
New_CW.show(e.screenX-drag_x, e.screenY-drag_y, CW_width, CW_height);
return false;
}
}

function drag_down(e){
if(e.button==2)return;
if(New_CW.document.body.offsetWidth==screen.width && New_CW.document.body.offsetHeight==screen.height)return;
drag_x=e.clientX;
drag_y=e.clientY;
draging=true;
e.srcElement.setCapture();
}

function drag_up(e){
draging=false;
e.srcElement.releaseCapture();
if(New_CW.document.body.offsetWidth==screen.width && New_CW.document.body.offsetHeight==screen.height) return;
CW_top = e.screenX-drag_x;
CW_left = e.screenY-drag_y;
}

</SCRIPT>
</HTML>

电话号码的验证

要求:
  (1)电话号码由数字、"("、")"和"-"构成
  (2)电话号码为3到8位
  (3)如果电话号码中包含有区号,那么区号为三位或四位
  (4)区号用"("、")"或"-"和其他部分隔开
  (5)移动电话号码为11或12位,如果为12位,那么第一位为0
  (6)11位移动电话号码的第一位和第二位为"13"
  (7)12位移动电话号码的第二位和第三位为"13"
  根据这几条规则,可以与出以下正则表达式
  (^[0-9]{3,4}\-[0-9]{3,8}$)|(^[0-9]{3,8}$)|(^\([0-9]{3,4}\)[0-9]{3,8}$)|(^0{0,1}13[0-9]{9}$)


<script language="javascript">
function PhoneCheck(s) {
var str=s;
var reg=/(^[0-9]{3,4}\-[0-9]{3,8}$)|(^[0-9]{3,8}$)|(^\([0-9]{3,4}\)[0-9]{3,8}$)|(^0{0,1}13[0-9]{9}$)/
alert(reg.test(str));
}
</script>
<input type=text name="iphone">
<input type=button onclick="PhoneCheck(document.all.iphone.value)" value="Check">

具有在输入非数字字符不回显的效果,即对非数字字符的输入不作反应。
function numbersonly(field,event){
var key,keychar;
if(window.event){
key = window.event.keyCode;
}
else if (event){
key = event.which;
}
else{
return true
}
keychar = String.fromCharCode(key);
if((key == null)||(key == 0)||(key == 8)||(key == 9)||(key == 13)||(key == 27)){
return true;
}
else if(("0123456789.").indexOf(keychar)>-1){
window.status = "";
return true;
}
else {
window.status = "Field excepts numbers only";
return false;
}
}

验证ip

str=document.RegExpDemo.txtIP.value;
if(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.test(str)==false)
{
window.alert('错误的IP地址格式');
document.RegExpDemo.txtIP.select();
document.RegExpDemo.txtIP.focus();
return;
}
if(RegExp.$1<1 || RegExp.$1>254||RegExp.$2<0||RegExp.$2>254||RegExp.$3<0||RegExp.$3>254||RegExp.$4<1||RegExp.$4>254)
{
window.alert('错误的IP地址');
document.RegExpDemo.txtIP.select();
document.RegExpDemo.txtIP.focus();
return;
}
//剔除 如 010.020.020.03 前面 的0
var str=str.replace(/0(\d)/g,"$1");
str=str.replace(/0(\d)/g,"$1");
window.alert(str);


//一下是取数据的类
//Obj参数指定数据的来源(限定Table),默认第一行为字段名称行
//GetTableData类提供MoveNext方法,参数是表的行向上或向下移动的位数,正数向下移动,负数向上.
//GetFieldData方法获得指定的列名的数据
//Sort_desc方法对指定的列按降序排列
//Sort_asc方法对指定的列按升序排列
//GetData方法返回字段值为特定值的数据数组,提供数据,可以在外部进行其他处理
//Delete方法删除当前记录,数组减少一行
//初始化,Obj:table的名字,Leftlen:左面多余数据长度,Rightlen:右面多余数据长度,
function GetTableData(Obj,LeftLen,RightLen){
var MyObj=document.all(Obj);
var iRow=MyObj.rows.length;
var iLen=MyObj.rows[0].cells.length;
var i,j;

TableData=new Array();
for (i=0;i< iRow;i++){
TableData[i]=new Array();
for (j=0;j<iLen;j++){
TableStr=MyObj.rows(i).cells(j).innerText;
TableStr=TableStr.substring(LeftLen, TableStr.length-RightLen).Trim();
TableStr=TableStr.replace(/ /gi,"").replace(/\r\n/ig,"");
TableData[i][j]=TableStr;
}
}

this.TableData=TableData;
this.cols=this.TableData[0].length;
this.rows=this.TableData.length;
this.rowindex=0;
}


function movenext(Step){
if (this.rowindex>=this.rows){
return
}

if (Step=="" || typeof(Step)=="undefined") {
if (this.rowindex<this.rows-1)
this.rowindex++;
return;

}
else{
if (this.rowindex + Step<=this.rows-1 && this.rowindex + Step>=0 ){
this.rowindex=this.rowindex + Step;
}
else
{
if (this.rowindex + Step<0){
this.rowindex= 0;
return;
}
if (this.rowindex + Step>this.rows-1){
this.rowindex= this.rows-1;
return;
}
}
}
}


function getfielddata(Field){
var colindex=-1;
var i=0;
if (typeof(Field) == "number"){
colindex=Field;
}
else
{
for (i=0;i<this.cols && this.rowindex<this.rows ;i++){
if (this.TableData[0][i]==Field){
colindex=i;
break;
}
}
}
if (colindex!=-1) {
return this.TableData[this.rowindex][colindex];
}

}



function sort_desc(){//降序
var colindex=-1;
var highindex=-1;
desc_array=new Array();
var i,j;
for (n=0; n<arguments.length; n++){
Field=arguments[arguments.length-1-n];
for (i=0;i<this.cols;i++){
if (this.TableData[0][i]==Field){
colindex=i;
break;
}
}
if ( colindex==-1 )
return;
else
{
desc_array[0]=this.TableData[0];
for(i=1;i<this.rows;i++){
desc_array[i]=this.TableData[1];
highindex=1;
for(j=1;j<this.TableData.length;j++){
if (desc_array[i][colindex]<this.TableData[j][colindex]){
desc_array[i]=this.TableData[j];
highindex=j;
}

}
if (highindex!=-1)
this.TableData=this.TableData.slice(0,highindex).concat(this.TableData.slice(highindex+1,this.TableData.length));
}
}


this.TableData=desc_array;
}
return;
}



function sort_asc(){//升序
var colindex=-1;
var highindex=-1;
var i,j;
for (n=0; n<arguments.length; n++){
asc_array=new Array();
Field=arguments[arguments.length-1-n];
for (i=0;i<this.cols;i++){
if (this.TableData[0][i]==Field){
colindex=i;
break;
}
}
if ( colindex==-1 )
return;
else
{
asc_array[0]=this.TableData[0];
for(i=1;i<this.rows;i++){
asc_array[i]=this.TableData[1];
highindex=1;
for(j=1;j<this.TableData.length;j++){//找出最小的列值
if (asc_array[i][colindex]>this.TableData[j][colindex]){
asc_array[i]=this.TableData[j];
highindex=j;

}

}
if (highindex!=-1)
this.TableData=this.TableData.slice(0,highindex).concat(this.TableData.slice(highindex+1,this.TableData.length));

}
}


this.TableData=asc_array;
}
return;
}



function getData(Field,FieldValue){
var colindex=-1;
var i,j;

GetData=new Array();
if (typeof(Field)=="undefined" || typeof(FieldValue)=="undefined" ){
return this.TableData;
}

for(j=0;j<this.cols;j++){
if (this.TableData[0][j]==Field){
colindex=j;
}
}
if (colindex!=-1){

for(i=1;i<this.rows;i++){
if (this.TableData[i][colindex]==FieldValue){
GetData[i]=new Array();
GetData[i]=this.TableData[i];
}
}
}
return GetData;
}
function DeletE(){
this.TableData=this.TableData.slice(0,this.rowindex).concat(this.TableData.slice(this.rowindex+1,this.TableData.length));
this.rows=this.TableData.length;
return;
}
function updateField(Field,FieldValue){
var colindex=-1;
var i=0;
if (typeof(Field) == "number"){
colindex=Field;
}
else
{
for (i=0;i<this.cols && this.rowindex<this.rows ;i++){
if (this.TableData[0][i]==Field){
colindex=i;
break;
}
}
}
if (colindex!=-1) {
this.TableData[this.rowindex][colindex]=FieldValue;
}


}
function movefirst(){
this.rowindex=0;
}
function movelast(){
this.rowindex=this.rows-1;
}
function String.prototype.Trim() {return this.replace(/(^\s*)|(\s*$)/g,"");}
GetTableData.prototype.MoveNext = movenext;
GetTableData.prototype.GetFieldData = getfielddata;
GetTableData.prototype.Sort_asc = sort_asc;
GetTableData.prototype.Sort_desc = sort_desc;
GetTableData.prototype.GetData = getData;
GetTableData.prototype.Delete = DeletE;
GetTableData.prototype.UpdateField = updateField;
GetTableData.prototype.MoveFirst = movefirst;

具体的例子:http://202.119.73.208/NetEAn/com/test/jsprint.htm

在每个文本框的onblur事件中调用校验代码,并且每个文本框中onKeyDown事件中写一个enter转tab函数

//回车键换为tab
function enterToTab()
{
if(event.srcElement.type != 'button' && event.srcElement.type != 'textarea'
&& event.keyCode == 13)
{
event.keyCode = 9;
}

2007/7/5

SQL的自动生成卡号和密码

declare @i bigint,@j int,@str nvarchar(160) ,@int_temp int,@str_temp nvarchar(10),@Card_NO nvarchar(10)
;
set @i = 10200001;
while (@i<=10250000)
begin
set @j = 0;
set @str='';
while (@j<=16)
begin
set @int_temp=rand()*9;
set @str_temp=str(@int_temp);
set @str=@str+@str_temp;
set @j=@j+1;
end
set @Card_NO=str(@i);
set @str=replace(@str,' ','');
insert into IN_Card (Card_No,[Password],[Value])values(@Card_NO,@str,100);
set @i=@i+1;
2007/3/17

Asp.Net防止刷新重复提交数据

  最近在用Asp.Net编写点东西时遇到个问题:即用户在提交表单后按刷新就会重复提交数据,即所谓的“刷新重复提交”的问题。在网上搜 一下,可以找到很多关于这方面的资料,其中有一篇是来自MSDN上的一种解决方法: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs05/html/BedrockASPNET.asp 它是通过重新定义 System.Web.UI.Page 类来实现加载页面时,是“刷新”、“后退”请求,还是正常请求,其他的页面则继承了自定义的这 个Page类。感觉他这个方法比较独特,有例子可以下载,有兴趣的可以研究研究。
网上最多的解决此类问题的方法就是不保存缓存,即提交后表单上的数据不会被浏览器的缓存保存,如果此时再遇到刷新或者后退请求时, 就会显示“网页已过期”,数据也就不会重复提交了,这就起到了阻止刷新重复提交的效果。
下面以简单的提交一篇帖子为例,介绍禁用缓存防止刷新重复提交的方法,表单数据包括“标题”和“正文”两个部分。
以下是该方法的代码(post.aspx):

CODE:
//页面加载
protected void Page_Load(object sender, EventArgs e)
{
   //可以在页面加载时设置页面的缓存为“SetNoStore()”,即无缓存
   Response.Cache.SetNoStore();
   //Session中存储的变量“IsSubmit”是标记是否提交成功的
   if ((bool)Session["IsSubmit"])
   {
     //如果表单数据提交成功,就设“Session["IsSubmit"]”为false
     Session["IsSubmit"] = false;
     //显示提交成功信息
     ShowMsg.Text = " * 提交成功!";
   }
   else
     //否则的话(没有提交,或者是页面刷新),不显示任何信息
     ShowMsg.Text = "";
}
//提交按钮(btnOK)单击事件
protected void btnOK_Click(object sender, EventArgs e)
{
   if (txtTitle.Text.ToString().Trim() == "")
     //ShowMsg是用来显示提示信息的
     ShowMsg.Text = " * 标题不能为空!";
  else if (txtText.Text.ToString().Trim() == "")
     ShowMsg.Text = " * 内容不能为空!";
  else
   {
     //这里是将数据提交到数据库中,省略
     /*
     string sql = "insert into tab...values(...)";
     MyConn.ExecQuery(sql);
     */
     //提交成功后,设“Session["IsSubmit"]”为true
     Session["IsSubmit"] = true;
     //强制转换页面(不可少,否则刷新仍会重复提交,仍转到本页),
     通过页面的转换将缓存中的提交的数据都释放了,即提交的标单数据不会被保存到缓存里,
     如果后退的话,将会出现该页无法显示
     Response.Redirect("post.aspx");
  }
}

上面这个方法非常简单也很实用,推荐大家使用。
下面是我自己研究出来的另一种方法,该方法不同于“不保存缓存的方法”,它是让浏览器保存所有页面缓存的。该方法通过随机码的方式 来判断是正常提交还是“刷新”或“后退”的。
首先(提交页面是post.aspx)在 Session 中 增加变量 Rnd 用来存放随机码,同时在提交表单数据时不做处理,而是让页面转到 post.aspx?r=x,这里“x”等于Session["Rnd"],这个时候在页面加载时,通过判断r的值和Session["Rnd"]的值是否相同,如果相同就处理提 交的数据,否则即可认为是“刷新”或者是“后退”操作了,最后再次付给Session["Rnd"]一个随机码。
以下是该方法代码(post.aspx):
 
CODE:
//获取随机码
public class MyRnd
{
   public static string Rnd()
   {
     //随机码是由 0-9 a-z A-Z 之间的数字或字母组成的
     //下面是生成的20位随机码
     //0..9 A..Z a..z
     //48-57 65-90 97-122
     string rst = "";
     Random rr = new Random();
     for (int i = 0; i < 20; i++)
     {
       int ir = 0;
       do
       {
         ir = rr.Next(123);
         if((ir >= 48) && (ir <= 57)) break;
         else if((ir >= 65) && (ir <= 90)) break;
         else if ((ir >= 97) && (ir <= 122)) break;
       }
       while (true);
       rst += ((char)ir).ToString();
       }
     return rst;
   }
}
//页面加载
protected void Page_Load(object sender, EventArgs e)
{
   //获取URL中请求的“r”值,如果“r”不存在则 r=""
   string r = "";
   if(Request.QueryString["r"] != null)
     r = Request.QueryString["r"].ToString().Trim();
   string t;
   //获取 “Session” 中的 “Rnd” 值,用于和“r”比较
   t = Session["Rnd"].ToString().Trim();
   //如果“r=t”则为提交操作,即可对表单的数据进行处理
  if(r == t)
  {
     if (txtTitle.Text.ToString().Trim() == "")
       ShowMsg.Text = " * 标题不能为空!";
     else if (txtText.Text.ToString().Trim() == "")
       ShowMsg.Text = " * 内容不能为空!";
     else      {
       //这里是将数据提交到数据库中,省略
       /*
       string sql = "insert into tab...values(...)";
       MyConn.ExecQuery(sql);
       */
       //提交成功后清空表单数据
       txtTitle.Text = "";
       txtText.Text = "";
       //显示提交成功信息
       ShowMsg.Text = " * 提交成功!";
     }
  }
   //否则可以认为是“刷新”或者“后退”操作
   else
   {
       txtTitle.Text = "";
       txtText.Text = "";
  }
  //最后要重新获得“Session["Rnd"]”的值,并将“btnOK.PostBackUrl”设为“Session["Rnd"]”的值
  Session["Rnd"] = MyRnd.Rnd();
  btnOK.PostBackUrl ="post.aspx?r=" + Session["Rnd"].ToString().Trim();
}
//这里提交按钮(btnOK)单击事件就不需要写任何代码了

通过这种方法,每次加载页面时“Session["Rnd"]”都将得到一个新的值,而在刷新或后退时就不会得到相同的“r”和“t”值,数据也就 不会被重复提交,只有通过“btnOK”来提交的操作才会得到“r==t”,数据才会被提交处理的,通过判断随机码的方式来阻止刷新重复提交就 可以实现了。
2007/2/8

提高SQL Server性能

有时,为了让应用程序运行得更快,所做的全部工作就是在这里或那里做一些很小调整。但关键在于确定如何进行调整!迟早您会遇到这种情况:应用程序中的 SQL 查询不能按照您想要的方式进行响应。它要么不返回数据,要么耗费的时间长得出奇。如果它降低了企业应用程序的速度,用户必须等待很长时间。用户希望应用程序响应迅速,他们的报告能够在瞬间之内返回分析数据。就我自己而言,如果在Web上冲浪时某个页面要耗费十多秒才能加载,我也会很不耐烦。

  为了解决这些问题,重要的是找到问题的根源。那么,从哪里开始呢?根本原因通常在于数据库设计和访问它的查询。我将讲述四项技术,这些技术可用于提高基于SQL Server的应用程序的性能或改善其可伸缩性。我将仔细说明 LEFT JOIN、CROSS JOIN 的使用以及IDENTITY 值的检索。请记住,根本没有神奇的解决方案。调整您的数据库及其查询需要占用时间、进行分析,还需要大量的测试。这些技术都已被证明行之有效,但对您的应用程序而言,可能其中一些技术比另一些技术更适用。

  从 INSERT 返回 IDENTITY

  我决定从遇到许多问题的内容入手:如何在执行SQL INSERT后检索IDENTITY值。通常,问题不在于如何编写检索值的查询,而在于在哪里以及何时进行检索。在SQL Server中,下面的语句可用于检索由最新在活动数据库连接上运行的 SQL 语句所创建的 IDENTITY 值:

  SELECT @@IDENTITY

  这个 SQL 语句并不复杂,但需要记住的一点是:如果这个最新的 SQL 语句不是 INSERT,或者您针对非 INSERT SQL 的其他连接运行了此 SQL,则不会获得期望的值。您必须运行下列代码才能检索紧跟在 INSERT SQL 之后且位于同一连接上的 IDENTITY,如下所示:

  INSERT INTO Products (ProductName) VALUES ('Chalk')

  SELECT @@IDENTITY

  在一个连接上针对 Northwind 数据库运行这些查询将返回一个名称为 Chalk 的新产品的 IDENTITY 值。所以,在使用ADOVisual Basic应用程序中,可以运行以下语句:

  Set oRs = oCn.Execute("SET NOCOUNT ON;INSERT INTO Products _

  (ProductName) VALUES ('Chalk');SELECT @@IDENTITY")

  lProductID = oRs(0) 

  此代码告诉 SQL Server 不要返回查询的行计数,然后执行 INSERT 语句,并返回刚刚为这个新行创建的 IDENTITY 值。SET NOCOUNT ON 语句表示返回的记录集有一行和一列,其中包含了这个新的 IDENTITY 值。如果没有此语句,则会首先返回一个空的记录集(因为 INSERT 语句不返回任何数据),然后会返回第二个记录集,第二个记录集中包含 IDENTITY 值。这可能有些令人困惑,尤其是因为您从来就没有希望过 INSERT 会返回记录集。之所以会发生此情况,是因为 SQL Server 看到了这个行计数(即一行受到影响)并将其解释为表示一个记录集。因此,真正的数据被推回到了第二个记录集。当然您可以使用 ADO 中的 NextRecordset 方法获取此第二个记录集,但如果总能够首先返回该记录集且只返回该记录集,则会更方便,也更有效率。

  此方法虽然有效,但需要在 SQL 语句中额外添加一些代码。获得相同结果的另一方法是在 INSERT 之前使用 SET NOCOUNT ON 语句,并将 SELECT @@IDENTITY 语句放在表中的 FOR INSERT 触发器中,如下面的代码片段所示。这样,任何进入该表的 INSERT 语句都将自动返回 IDENTITY 值。

  CREATE TRIGGER trProducts_Insert ON Products FOR INSERT AS

  SELECT @@IDENTITY

  GO

  触发器只在 Products 表上发生 INSERT 时启动,所以它总是会在成功 INSERT 之后返回一个 IDENTITY。使用此技术,您可以始终以相同的方式在应用程序中检索 IDENTITY 值。

内嵌视图与临时表

  某些时候,查询需要将数据与其他一些可能只能通过执行 GROUP BY 然后执行标准查询才能收集的数据进行联接。例如,如果要查询最新五个定单的有关信息,您首先需要知道是哪些定单。这可以使用返回定单 ID 的 SQL 查询来检索。此数据就会存储在临时表(这是一个常用技术)中,然后与 Products 表进行联接,以返回这些定单售出的产品数量:

  CREATE TABLE #Temp1 (OrderID INT NOT NULL, _

  OrderDate DATETIME NOT NULL)

  INSERT INTO #Temp1 (OrderID, OrderDate)

  SELECT TOP 5 o.OrderID, o.OrderDate

  FROM Orders o ORDER BY o.OrderDate DESC

  SELECT p.ProductName, SUM(od.Quantity) AS ProductQuantity

  FROM #Temp1 t

  INNER JOIN [Order Details] od ON t.OrderID = od.OrderID

  INNER JOIN Products p ON od.ProductID = p.ProductID

  GROUP BY p.ProductName

  ORDER BY p.ProductName

  DROP TABLE #Temp1

  这些 SQL 语句会创建一个临时表,将数据插入该表中,将其他数据与该表进行联接,然后除去该临时表。这会导致此查询进行大量 I/O 操作,因此,可以重新编写查询,使用内嵌视图取代临时表。内嵌视图只是一个可以联接到 FROM 子句中的查询。所以,您不用在 tempdb 中的临时表上耗费大量 I/O 和磁盘访问,而可以使用内嵌视图得到同样的结果:

  SELECT p.ProductName,

  SUM(od.Quantity) AS ProductQuantity

  FROM (

  SELECT TOP 5 o.OrderID, o.OrderDate

  FROM Orders o

  ORDER BY o.OrderDate DESC

  ) t

  INNER JOIN [Order Details] od ON t.OrderID = od.OrderID

  INNER JOIN Products p ON od.ProductID = p.ProductID

  GROUP BY

  p.ProductName

  ORDER BY

  p.ProductName

  此查询不仅比前面的查询效率更高,而且长度更短。临时表会消耗大量资源。如果只需要将数据联接到其他查询,则可以试试使用内嵌视图,以节省资源。

  避免 LEFT JOIN 和 NULL

  当然,有很多时候您需要执行 LEFT JOIN 和使用 NULL 值。但是,它们并不适用于所有情况。改变 SQL 查询的构建方式可能会产生将一个花几分钟运行的报告缩短到只花几秒钟这样的天壤之别的效果。有时,必须在查询中调整数据的形态,使之适应应用程序所要求的显示方式。虽然 TABLE 数据类型会减少大量占用资源的情况,但在查询中还有许多区域可以进行优化。SQL 的一个有价值的常用功能是 LEFT JOIN。它可以用于检索第一个表中的所有行、第二个表中所有匹配的行、以及第二个表中与第一个表不匹配的所有行。例如,如果希望返回每个客户及其定单,使用 LEFT JOIN 则可以显示有定单和没有定单的客户。

  此工具可能会被过度使用。LEFT JOIN 消耗的资源非常之多,因为它们包含与 NULL(不存在)数据匹配的数据。在某些情况下,这是不可避免的,但是代价可能非常高。LEFT JOIN 比 INNER JOIN 消耗资源更多,所以如果您可以重新编写查询以使得该查询不使用任何 LEFT JOIN,则会得到非常可观的回报。

  加快使用 LEFT JOIN 的查询速度的一项技术涉及创建一个 TABLE 数据类型,插入第一个表(LEFT JOIN 左侧的表)中的所有行,然后使用第二个表中的值更新 TABLE 数据类型。此技术是一个两步的过程,但与标准的 LEFT JOIN 相比,可以节省大量时间。一个很好的规则是尝试各种不同的技术并记录每种技术所需的时间,直到获得用于您的应用程序的执行性能最佳的查询。

  测试查询的速度时,有必要多次运行此查询,然后取一个平均值。因为查询(或存储过程)可能会存储在 SQL Server 内存中的过程缓存中,因此第一次尝试耗费的时间好像稍长一些,而所有后续尝试耗费的时间都较短。另外,运行您的查询时,可能正在针对相同的表运行其他查询。当其他查询锁定和解锁这些表时,可能会导致您的查询要排队等待。例如,如果您进行查询时某人正在更新此表中的数据,则在更新提交时您的查询可能需要耗费更长时间来执行。

  避免使用 LEFT JOIN 时速度降低的最简单方法是尽可能多地围绕它们设计数据库。例如,假设某一产品可能具有类别也可能没有类别。如果 Products 表存储了其类别的 ID,而没有用于某个特定产品的类别,则您可以在字段中存储 NULL 值。然后您必须执行 LEFT JOIN 来获取所有产品及其类别。您可以创建一个值为“No Category”的类别,从而指定外键关系不允许 NULL 值。通过执行上述操作,现在您就可以使用 INNER JOIN 检索所有产品及其类别了。虽然这看起来好像是一个带有多余数据的变通方法,但可能是一个很有价值的技术,因为它可以消除 SQL 批处理语句中消耗资源较多的 LEFT JOIN。在数据库中全部使用此概念可以为您节省大量的处理时间。请记住,对于您的用户而言,即使几秒钟的时间也非常重要,因为当您有许多用户正在访问同一个联机数据库应用程序时,这几秒钟实际上的意义会非常重大。

灵活使用笛卡尔乘积

  对于此技巧,我将进行非常详细的介绍,并提倡在某些情况下使用笛卡尔乘积。出于某些原因,笛卡尔乘积 (CROSS JOIN) 遭到了很多谴责,开发人员通常会被警告根本就不要使用它们。在许多情况下,它们消耗的资源太多,从而无法高效使用。但是像 SQL 中的任何工具一样,如果正确使用,它们也会很有价值。例如,如果您想运行一个返回每月数据(即使某一特定月份客户没有定单也要返回)的查询,您就可以很方便地使用笛卡尔乘积。

  虽然这看起来好像没什么神奇的,但是请考虑一下,如果您从客户到定单(这些定单按月份进行分组并对销售额进行小计)进行了标准的 INNER JOIN,则只会获得客户有定单的月份。因此,对于客户未订购任何产品的月份,您不会获得 0 值。如果您想为每个客户都绘制一个图,以显示每个月和该月销售额,则可能希望此图包括月销售额为 0 的月份,以便直观标识出这些月份。如果使用 Figure 2(最后一页) 中的 SQL,数据则会跳过销售额为 0 美元的月份,因为在定单表中对于零销售额不会包含任何行(假设您只存储发生的事件)。

  Figure 3(最后一页)中的代码虽然较长,但是可以达到获取所有销售数据(甚至包括没有销售额的月份)的目标。首先,它会提取去年所有月份的列表,然后将它们放入第一个 TABLE 数据类型表 (@tblMonths) 中。下一步,此代码会获取在该时间段内有销售额的所有客户公司的名称列表,然后将它们放入另一个 TABLE 数据类型表 (@tblCus-tomers) 中。这两个表存储了创建结果集所必需的所有基本数据,但实际销售数量除外。 第一个表中列出了所有月份(12 行),第二个表中列出了这个时间段内有销售额的所有客户(对于我是 81 个)。并非每个客户在过去 12 个月中的每个月都购买了产品,所以,执行 INNER JOIN 或 LEFT JOIN 不会返回每个月的每个客户。这些操作只会返回购买产品的客户和月份。

  笛卡尔乘积则可以返回所有月份的所有客户。笛卡尔乘积基本上是将第一个表与第二个表相乘,生成一个行集合,其中包含第一个表中的行数与第二个表中的行数相乘的结果。因此,笛卡尔乘积会向表 @tblFinal 返回 972 行。最后的步骤是使用此日期范围内每个客户的月销售额总计更新 @tblFinal 表,以及选择最终的行集。

  如果由于笛卡尔乘积占用的资源可能会很多,而不需要真正的笛卡尔乘积,则可以谨慎地使用 CROSS JOIN。例如,如果对产品和类别执行了 CROSS JOIN,然后使用 WHERE 子句、DISTINCT 或 GROUP BY 来筛选出大多数行,那么使用 INNER JOIN 会获得同样的结果,而且效率高得多。如果需要为所有的可能性都返回数据(例如在您希望使用每月销售日期填充一个图表时),则笛卡尔乘积可能会非常有帮助。但是,您不应该将它们用于其他用途,因为在大多数方案中 INNER JOIN 的效率要高得多。

  拾遗补零

  这里介绍其他一些可帮助提高 SQL 查询效率的常用技术。假设您将按区域对所有销售人员进行分组并将他们的销售额进行小计,但是您只想要那些数据库中标记为处于活动状态的销售人员。您可以按区域对销售人员分组,并使用 HAVING 子句消除那些未处于活动状态的销售人员,也可以在 WHERE 子句中执行此操作。在 WHERE 子句中执行此操作会减少需要分组的行数,所以比在 HAVING 子句中执行此操作效率更高。HAVING 子句中基于行的条件的筛选会强制查询对那些在 WHERE 子句中会被去除的数据进行分组。

  另一个提高效率的技巧是使用 DISTINCT 关键字查找数据行的单独报表,来代替使用 GROUP BY 子句。在这种情况下,使用 DISTINCT 关键字的 SQL 效率更高。请在需要计算聚合函数(SUM、COUNT、MAX 等)的情况下再使用 GROUP BY。另外,如果您的查询总是自己返回一个唯一的行,则不要使用 DISTINCT 关键字。在这种情况下,DISTINCT 关键字只会增加系统开销。

  您已经看到了,有大量技术都可用于优化查询和实现特定的业务规则,技巧就是进行一些尝试,然后比较它们的性能。最重要的是要测试、测试、再测试。

Figure 2 Returning All Customers and Their Sales

set nocount on

DECLARE @dtStartDate DATETIME,

@dtEndDate DATETIME,

@dtDate DATETIME

SET @dtEndDate = '5/5/1997'

SET @dtEndDate = DATEADD(DD, -1, CAST(CAST((MONTH(@dtEndDate) + 1)

AS VARCHAR(2)) + '/01/' + CAST(YEAR(@dtEndDate) AS VARCHAR(4)) + '

23:59:59' AS DATETIME))

SET @dtStartDate = DATEADD(MM, -1 * 12, @dtEndDate)

SELECT CAST(YEAR(o.OrderDate) AS VARCHAR(4)) + '-' +

CASE

WHEN MONTH(o.OrderDate) < 10

THEN '0' + CAST(MONTH(o.OrderDate) AS VARCHAR(2))

ELSE CAST(MONTH(o.OrderDate) AS VARCHAR(2))

END AS sMonth,

c.CustomerID,

c.CompanyName,

c.ContactName,

SUM(od.Quantity * od.UnitPrice) AS mSales

FROM Customers c

INNER JOIN Orders o ON c.CustomerID = o.CustomerID

INNER JOIN [Order Details] od ON o.OrderID = od.OrderID

WHERE o.OrderDate BETWEEN @dtStartDate AND @dtEndDate

GROUP BY

CAST(YEAR(o.OrderDate) AS VARCHAR(4)) + '-' +

CASE

WHEN MONTH(o.OrderDate) < 10

THEN '0' + CAST(MONTH(o.OrderDate) AS VARCHAR(2))

ELSE CAST(MONTH(o.OrderDate) AS VARCHAR(2))

END,

c.CustomerID,

c.CompanyName,

c.ContactName

ORDER BY

c.CompanyName,

sMonth-------------------------------------------------------------------------------------------------------------------------------------

Figure 3 Cartesian Product at Work

DECLARE @tblMonths TABLE (sMonth VARCHAR(7))

DECLARE @tblCustomers TABLE ( CustomerID CHAR(10),

CompanyName VARCHAR(50),

ContactName VARCHAR(50))

DECLARE @tblFinal TABLE ( sMonth VARCHAR(7),

CustomerID CHAR(10),

CompanyName VARCHAR(50),

ContactName VARCHAR(50),

mSales MONEY)

DECLARE @dtStartDate DATETIME,

@dtEndDate DATETIME,

@dtDate DATETIME,

@i INTEGER

SET @dtEndDate = '5/5/1997'

SET @dtEndDate = DATEADD(DD, -1, CAST(CAST((MONTH(@dtEndDate) + 1) AS

VARCHAR(2)) + '/01/' + CAST(YEAR(@dtEndDate) AS VARCHAR(4)) + '

23:59:59' AS DATETIME))

SET @dtStartDate = DATEADD(MM, -1 * 12, @dtEndDate)

— Get all months into the first table

SET @i = 0

WHILE (@i < 12)

BEGIN

SET @dtDate = DATEADD(mm, -1 * @i, @dtEndDate)

INSERT INTO @tblMonths SELECT CAST(YEAR(@dtDate) AS VARCHAR(4)) + '-' +

CASE

WHEN MONTH(@dtDate) < 10

THEN '0' + CAST(MONTH(@dtDate) AS VARCHAR(2))

ELSE CAST(MONTH(@dtDate) AS VARCHAR(2))

END AS sMonth

SET @i = @i + 1

END

— Get all clients who had sales during that period into the "y" table

INSERT INTO @tblCustomers

SELECT DISTINCT

c.CustomerID,

c.CompanyName,

c.ContactName

FROM Customers c

INNER JOIN Orders o ON c.CustomerID = o.CustomerID

WHERE o.OrderDate BETWEEN @dtStartDate AND @dtEndDate

INSERT INTO @tblFinal

SELECT m.sMonth,

c.CustomerID,

c.CompanyName,

c.ContactName,

0

FROM @tblMonths m CROSS JOIN @tblCustomers c

UPDATE @tblFinal SET

mSales = mydata.mSales

FROM @tblFinal f INNER JOIN

(

SELECT c.CustomerID,

CAST(YEAR(o.OrderDate) AS VARCHAR(4)) + '-' +

CASE WHEN MONTH(o.OrderDate) < 10

THEN '0' + CAST(MONTH(o.OrderDate) AS VARCHAR(2))

ELSE CAST(MONTH(o.OrderDate) AS VARCHAR(2))

END AS sMonth,

SUM(od.Quantity * od.UnitPrice) AS mSales

FROM Customers c

INNER JOIN Orders o ON c.CustomerID = o.CustomerID

INNER JOIN [Order Details] od ON o.OrderID = od.OrderID

WHERE o.OrderDate BETWEEN @dtStartDate AND @dtEndDate

GROUP BY

c.CustomerID,

CAST(YEAR(o.OrderDate) AS VARCHAR(4)) + '-' +

CASE WHEN MONTH(o.OrderDate) < 10

THEN '0' + CAST(MONTH(o.OrderDate) AS VARCHAR(2))

ELSE CAST(MONTH(o.OrderDate) AS VARCHAR(2))

END

) mydata on f.CustomerID = mydata.CustomerID AND f.sMonth =

mydata.sMonth

SELECT f.sMonth,

f.CustomerID,

f.CompanyName,

f.ContactName,

f.mSales

FROM @tblFinal f

ORDER BY

f.CompanyName,

f.sMonth

SQL Server存储过程

首先介绍一下什么是存储过程:存储过程就是将常用的或很复杂的工作,预先用SQL语句写好并用一个指定的名称存储起来,并且这样的语句是放在数据库中的,还可以根据条件执行不同SQL语句,那么以后要叫数据库提供与已定义好的存储过程的功能相同的服务时,只需调用execute,即可自动完成命令。

  请大家来了解一下存储过程的语法。

  CREATE PROC [ EDURE ] procedure_name [ ; number ]
[ { @parameter data_type }
[ VARYING ] [ = default ] [ OUTPUT ]
] [ ,...n ]

  [ WITH
{ RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION } ]

  [ FOR REPLICATION ]

  AS sql_statement [ ...n ]

  参数:

  procedure_name

  新存储过程的名称。过程名必须符合标识符规则,且对于数据库及其所有者必须唯一。

  要创建局部临时过程,可以在 procedure_name 前面加一个编号符 (#procedure_name),要创建全局临时过程,可以在 procedure_name 前面加两个编号符 (##procedure_name)。完整的名称(包括 # 或 ##)不能超过 128 个字符。指定过程所有者的名称是可选的。

  ;number

  是可选的整数,用来对同名的过程分组,以便用一条 DROP PROCEDURE 语句即可将同组的过程一起除去。例如,名为 orders 的应用程序使用的过程可以命名为 orderproc;1、orderproc;2 等。DROP PROCEDURE orderproc 语句将除去整个组。如果名称中包含定界标识符,则数字不应包含在标识符中,只应在 procedure_name 前后使用适当的定界符。

  @parameter

  过程中的参数。在 CREATE PROCEDURE 语句中可以声明一个或多个参数。用户必须在执行过程时提供每个所声明参数的值(除非定义了该参数的默认值)。存储过程最多可以有 2100 个参数。

  使用@符号作为第一个字符来指定参数名称。参数名称必须符合标识符的规则。每个过程的参数仅用于该过程本身;相同的参数名称可以用在其它过程中。默认情况下,参数只能代替常量,而不能用于代替表名、列名或其它数据库对象的名称。

  data_type

  参数的数据类型。所有数据类型(包括 text、ntext 和 image)均可以用作存储过程的参数。不过,cursor 数据类型只能用于 OUTPUT 参数。如果指定的数据类型为 cursor,也必须同时指定 VARYING 和 OUTPUT 关键字。

  说明:对于可以是cursor 数据类型的输出参数,没有最大数目的限制。

VARYING

  指定作为输出参数支持的结果集(由存储过程动态构造,内容可以变化)。仅适用于游标参数。

  default

  参数的默认值。如果定义了默认值,不必指定该参数的值即可执行过程。默认值必须是常量或 NULL。如果过程将对该参数使用 LIKE 关键字,那么默认值中可以包含通配符(%、_、[] 和 [^])。

  OUTPUT

  表明参数是返回参数。该选项的值可以返回给 EXEC[UTE]。使用 OUTPUT 参数可将信息返回给调用过程。Text、ntext 和 image 参数可用作 OUTPUT 参数。使用 OUTPUT 关键字的输出参数可以是游标占位符。

  n

  表示最多可以指定 2100 个参数的占位符。

  {RECOMPILE | ENCRYPTION | RECOMPILE, ENCRYPTION}
RECOMPILE 表明 SQL Server 不会缓存该过程的计划,该过程将在运行时重新编译。在使用非典型值或临时值而不希望覆盖缓存在内存中的执行计划时,请使用 RECOMPILE 选项。

  ENCRYPTION 表示 SQL Server 加密 syscomments 表中包含 CREATE PROCEDURE 语句文本的条目。使用 ENCRYPTION 可防止将过程作为 SQL Server 复制的一部分发布。

  说明:在升级过程中,SQL Server 利用存储在 syscomments 中的加密注释来重新创建加密过程。

  FOR REPLICATION

  指定不能在订阅服务器上执行为复制创建的存储过程。.使用 FOR REPLICATION 选项创建的存储过程可用作存储过程筛选,且只能在复制过程中执行。本选项不能和 WITH RECOMPILE 选项一起使用。

  AS

  指定过程要执行的操作。

  sql_statement

  过程中要包含的任意数目和类型的 Transact-SQL 语句。但有一些限制。

  n

  是表示此过程可以包含多条 Transact-SQL 语句的占位符。

  注释

  存储过程的最大大小为 128 MB。

存储过程的优点都有哪些呢?

  1.存储过程只在创造时进行编译即可,以后每次执行存储过程都不需再重新编译,而我们通常使用的SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。

  2.经常会遇到复杂的业务逻辑和对数据库的操作,这个时候就会用SP来封装数据库操作。当对数据库进行复杂操作时(如对多个表进行Update, Insert,Query,Delete时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。可以极大的提高数据库的使用效率,减少程序的执行时间,这一点在较大数据量的数据库的操作中是非常重要的。在代码上看,SQL语句和程序代码语句的分离,可以提高程序代码的可读性。

  3.存储过程可以设置参数,可以根据传入参数的不同重复使用同一个存储过程,从而高效的提高代码的优化率和可读性。

  4.安全性高,可设定只有某此用户才具有对指定存储过程的使用权存储过程的种类:

  (1)系统存储过程:以sp_开头,用来进行系统的各项设定.取得信息.相关管理工作,如 sp_help就是取得指定对象的相关信息。

  (2)扩展存储过程 以XP_开头,用来调用操作系统提供的功能
exec master..xp_cmdshell 'ping 10.8.16.1'

  (3)用户自定义的存储过程,这是我们所指的存储过程常用格式

  模版:Create procedure procedue_name [@parameter data_type][output]
[with]{recompile|encryption} as sql_statement

  解释:output:表示此参数是可传回的

  with {recompile|encryption} recompile:表示每次执行此存储过程时都重新编译一次;encryption:所创建的存储过程的内容会被加密。

实例1:只返回单一记录集的存储过程。

  表银行存款表(bankMoney)的内容如下

Id

userID

Sex

Money

001

Zhangsan

30

002

Wangwu

50

003

Zhangsan

40

要求1:查询表bankMoney的内容的存储过程

create procedure sp_query_bankMoney
as
select * from bankMoney
go
exec sp_query_bankMoney

注* 在使用过程中只需要把中的SQL语句替换为存储过程名,就可以了很方便吧!

  实例2(向存储过程中传递参数):

加入一笔记录到表bankMoney,并查询此表中userID= Zhangsan的所有存款的总金额。

Create proc insert_bank @param1 char(10),@param2 varchar(20),@param3 varchar(20),@param4 int,@param5 int output
with encryption ---------加密
as
insert bankMoney (id,userID,sex,Money)
Values(@param1,@param2,@param3, @param4)
select @param5=sum(Money) from bankMoney where userID='Zhangsan'
go
在SQL Server查询分析器中执行该存储过程的方法是:
declare @total_price int
exec insert_bank '004','Zhangsan','男',100,@total_price output
print '总余额为'+convert(varchar,@total_price)
go

在这里再啰嗦一下存储过程的3种传回值(方便正在看这个例子的朋友不用再去查看语法内容):

1.以Return传回整数
2.以output格式传回参数
3.Recordset

传回值的区别:

output和return都可在批次程式中用变量接收,而recordset则传回到执行批次的客户端中。

实例3:使用带有复杂 SELECT 语句的简单过程

  下面的存储过程从四个表的联接中返回所有作者(提供了姓名)、出版的书籍以及出版社。该存储过程不使用任何参数。

  USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'au_info_all' AND type = 'P')
DROP PROCEDURE au_info_all
GO
CREATE PROCEDURE au_info_all
AS
SELECT au_lname, au_fname, title, pub_name
FROM authors a INNER JOIN titleauthor ta
ON a.au_id = ta.au_id INNER JOIN titles t
ON t.title_id = ta.title_id INNER JOIN publishers p
ON t.pub_id = p.pub_id
GO

  au_info_all 存储过程可以通过以下方法执行:

  EXECUTE au_info_all
-- Or
EXEC au_info_all

  如果该过程是批处理中的第一条语句,则可使用:

  au_info_all

  实例4:使用带有参数的简单过程

  CREATE PROCEDURE au_info
@lastname varchar(40),
@firstname varchar(20)
AS
SELECT au_lname, au_fname, title, pub_name
FROM authors a INNER JOIN titleauthor ta
ON a.au_id = ta.au_id INNER JOIN titles t
ON t.title_id = ta.title_id INNER JOIN publishers p
ON t.pub_id = p.pub_id
WHERE au_fname = @firstname
AND au_lname = @lastname
GO

  au_info 存储过程可以通过以下方法执行:

  EXECUTE au_info 'Dull', 'Ann'
-- Or
EXECUTE au_info @lastname = 'Dull', @firstname = 'Ann'
-- Or
EXECUTE au_info @firstname = 'Ann', @lastname = 'Dull'
-- Or
EXEC au_info 'Dull', 'Ann'
-- Or
EXEC au_info @lastname = 'Dull', @firstname = 'Ann'
-- Or
EXEC au_info @firstname = 'Ann', @lastname = 'Dull'

  如果该过程是批处理中的第一条语句,则可使用:

  au_info 'Dull', 'Ann'
-- Or
au_info @lastname = 'Dull', @firstname = 'Ann'
-- Or
au_info @firstname = 'Ann', @lastname = 'Dull'

实例5:使用带有通配符参数的简单过程

CREATE PROCEDURE au_info2
@lastname varchar(30) = 'D%',
@firstname varchar(18) = '%'
AS
SELECT au_lname, au_fname, title, pub_name
FROM authors a INNER JOIN titleauthor ta
ON a.au_id = ta.au_id INNER JOIN titles t
ON t.title_id = ta.title_id INNER JOIN publishers p
ON t.pub_id = p.pub_id
WHERE au_fname LIKE @firstname
AND au_lname LIKE @lastname
GO

  au_info2 存储过程可以用多种组合执行。下面只列出了部分组合:

  EXECUTE au_info2
-- Or
EXECUTE au_info2 'Wh%'
-- Or
EXECUTE au_info2 @firstname = 'A%'
-- Or
EXECUTE au_info2 '[CK]ars[OE]n'
-- Or
EXECUTE au_info2 'Hunter', 'Sheryl'
-- Or
EXECUTE au_info2 'H%', 'S%'

  = 'proc2'

2007/1/4

Ajax Validate

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="login.aspx.cs" Inherits="AnsonWebShop.Web.login" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
    <link href="App_Themes/AnsonWebShop/test.css" type="text/css" rel="stylesheet" />
</head>
<body>
    <form id="form1" runat="server">
        <asp:Label ID="Label1" runat="server" Text="User:"></asp:Label>
        <input id="un" type="text" style="width: 150px" runat="server" onblur="checkEmailAddress(this.value, true);" /><div id="divE"></div><br />
        <asp:Label ID="Label2" runat="server" Text="Pass:"></asp:Label>
        <input id="pw" style="width: 150px" type="password" runat="server" /><br />
        <input id="Button1" style="width: 184px" runat="server" onclick="loginin()" value="OK" />&nbsp;&nbsp;
        &nbsp;&nbsp;&nbsp;
        <br />
         <input type="button" name="btNext" id="btNext" onclick="return checkEmailBorad();" value="Next" class="joinbtn" />
        <br />
      <script language="javascript" type="text/javascript">
    function checkEmailAddress(strValue, isCheck)
{
    var str = strValue.trim();
    var uu = document.getElementById("un");
    var d = document.getElementById("divEmail");
    if(str.length < 1)
 {
  d.innerHTML = "<div class=\"check\">电子邮件地址不能为空</div>";
  return false;
 }
 else
 {
     var reg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
     if(checkReg(reg, str))
     {
         if(isCheck)
         {
             var url = "CEE.aspx";
          var pars = "EMail=" + StrCode(strValue);
          var acheck = new Ajaxcheck.check({success: "divE"}, url, {method: "post", parameters: pars, onLoading: function(){$("divE").innerHTML = "<div class=\"loading\">检测中,请稍后……</div>";}});
      }
      return true;
     }
     else
     {
         d.innerHTML = "<div class=\"checkerror\">电子邮件地址不合法</div>";
      return false;
     }
 }
}
function checkEmailBorad()
{
    if(checkEmailAddress("un", false))
    {
        
    }
    else
    {
        return false;
    }
}
      </script>
         </form>
</body>
</html>
2007/1/3

Ajax Tree

1.建立一个aspx页面
html代码

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Ajax Tree</title>
<link type="text/css" href="../../Styles/tree_css/tree.css" rel="stylesheet">
</head>
<body>
<form id="Form1" runat="server">
<div class="TreeMenu" id="CategoryTree" style="width: 100%; height: 489px">
</div>
<script language="javascript" type="text/javascript">
function el(id)
{
return document.getElementById(id);
}
function ExpandSubCategory(iCategoryID)
{
var li_father = el("li_" + iCategoryID);
if (li_father.getElementsByTagName("li").length > 0) //分类已下载
{
ChangeStatus(iCategoryID);
return;
}

li_father.className = "Opened";

switchNote(iCategoryID, true);
AjaxMethod.GetSubCategory(iCategoryID, GetSubCategory_callback);
}

function GetSubCategory_callback(response)
{
var dt = response.value.Tables[0];
if (dt.Rows.length > 0)
{
var iCategoryID = dt.Rows[0].FatherID;
}
var li_father = el("li_" + iCategoryID);
var ul = document.createElement("ul");
for (var i = 0;i < dt.Rows.length;i++)
{
if (dt.Rows[i].IsChild == 1) //叶子节点
{
var li = document.createElement("li");
li.className = "Child";
li.id = "li_" + dt.Rows[i].CategoryID;

var img = document.createElement("img");
img.id = dt.Rows[i].CategoryID;
img.className = "s";
img.src = "../../Styles/tree_css/s.gif";

var a = document.createElement("a");
var id = dt.Rows[i].CategoryID;
a.onmouseover = function()
{
PreviewImage(id);
};
a.href = "javascript:OpenDocument('" + dt.Rows[i].CategoryID + "');";
a.innerHTML = dt.Rows[i].CategoryName;
}
else
{
var li = document.createElement("li");
li.className = "Closed";
li.id = "li_" + dt.Rows[i].CategoryID;

var img = document.createElement("img");
img.id = dt.Rows[i].CategoryID;
img.className = "s";
img.src = "../../Styles/tree_css/s.gif";
img.onclick = function () {
ExpandSubCategory(this.id);
};
img.alt = "展开/折叠";

var a = document.createElement("a");
a.href = "javascript:ExpandSubCategory(" +
dt.Rows[i].CategoryID + ");";
a.innerHTML = dt.Rows[i].CategoryName;
}
li.appendChild(img);
li.appendChild(a);
ul.appendChild(li);
}
li_father.appendChild(ul);

switchNote(iCategoryID, false);
}

// 叶子节点的单击响应函数
function OpenDocument(iCategoryID)
{
// 预加载信息
PreloadFormUrl(iCategoryID);
}

function PreviewImage(iCategoryID)
{

}

function ChangeStatus(iCategoryID)
{
var li_father = el("li_" + iCategoryID);
if (li_father.className == "Closed")
{
li_father.className = "Opened";
}
else
{
li_father.className = "Closed";
}
}

function switchNote(iCategoryID, show)
{
var li_father = el("li_" + iCategoryID);
if (show)
{
var ul = document.createElement("ul");
ul.id = "ul_note_" + iCategoryID;

var note = document.createElement("li");
note.className = "Child";

var img = document.createElement("img");
img.className = "s";
img.src = "../../Styles/tree_css/s.gif";

var a = document.createElement("a");
a.href = "javascript:void(0);";
a.innerHTML = "请稍候";

note.appendChild(img);
note.appendChild(a);
ul.appendChild(note);
li_father.appendChild(ul);
}
else
{
var ul = el("ul_note_" + iCategoryID);
if (ul)
{
li_father.removeChild(ul);
}
}
}

// 加载根节点
var tree = el("CategoryTree");
var root = document.createElement("li");
root.id = "li_0";
tree.appendChild(root);

// 加载页面时显示第一级分类
ExpandSubCategory(0);

function PreloadFormUrl(iCategoryID)
{
// 采用同步调用的方式获取图片的信息
var ds = AjaxMethod.GetFormsList(iCategoryID).value;
// 如果返回了结果
if (ds)
{
// 判断数据表是否不为空
if (ds.Tables[0].Rows.length > 0)
{
// 返回的信息数据表
dt = ds.Tables[0];
el("furl").src = dt.Rows[0].FormUrl;
}
else // 分类下没有
{
}
}
}
</script>
</form>
</body>
</html>



2.cs代码

using System;
using System.Data;
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;
using AjaxPro;

public partial class Pages_Home_HomePage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
AjaxPro.Utility.RegisterTypeForAjax(typeof(AjaxMethod));
}
}


3.建立一个tree.css的css样式

a
{
text-decoration:none;
}
a,a:visited
{
color:#000;
background:inherit;
}
body
{
margin:0;
padding:20px;
font:12px tahoma,宋体,sans-serif;
}
dt
{
font-size:22px;
font-weight:bold;
margin:0 0 0 15px;
}
dd
{
margin:0 0 0 15px;
}
h4
{
margin:0;
padding:0;
font-size:18px;
text-align:center;
}
p
{
margin:0;
padding:0 0 0 18px;
}
p a,p a:visited
{
color:#00f;
background:inherit;
}

.TreeMenu img.s
{
cursor:hand;
vertical-align:middle;
}
.TreeMenu ul
{
padding:0;
}
.TreeMenu li
{
list-style:none;
padding:0;
}
.Closed ul
{
display:none;
}
.Child img.s
{
background:none;
cursor:default;
}

#CategoryTree ul
{
margin:0 0 0 17px;
}
#CategoryTree img.s
{
width:34px;
height:18px;
}
#CategoryTree .Opened img.s
{
background:url(skin3/opened.gif) no-repeat 0 1px;
}
#CategoryTree .Closed img.s
{
background:url(skin3/closed.gif) no-repeat 0 1px;
}
#CategoryTree .Child img.s
{
background:url(skin3/child.gif) no-repeat 13px 2px;
}

#CategoryTree
{
float:left;
width:249px;
border:1px solid #99BEEF;
background:#D2E4FC;
color:inherit;
margin:3px;
padding:3px;
height:600px;
}


4.建立一个类AjaxMethod

using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
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;
using AjaxPro;

/**//// <summary>
/// Summary description for AjaxMethod
/// </summary>
public class AjaxMethod
{
public AjaxMethod()
{
//
// TODO: Add constructor logic here
//
}
[AjaxMethod(HttpSessionStateRequirement.ReadWrite)]
public static DataSet GetSubCategory(int iCategoryID)
{
string sql = string.Format("SELECT CategoryID, CategoryName, FatherID, dbo.IsLeaf(CategoryID) as IsChild FROM Category WHERE FatherID = {0}", iCategoryID);
return GetDataSet(sql);
}

[AjaxMethod(HttpSessionStateRequirement.ReadWrite)]
public static DataSet GetFormsList(int iCategoryID)
{
string sql = string.Format("SELECT * FROM forms WHERE form_category_id = {0}", iCategoryID);
return GetDataSet(sql);
}
public static string ConnectionString = ConfigurationSettings.AppSettings["ConnectionString"].ToString();

public static DataSet GetDataSet(string sql)
{
SqlDataAdapter sda = new SqlDataAdapter(sql, ConnectionString);
DataSet ds = new DataSet();
sda.Fill(ds);
if (ds != null)
return ds;
else
return null;
}
}


5.sql脚本

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Category]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Category]
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Forms]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Forms]
GO

CREATE TABLE [dbo].[Category] (
[CategoryID] [int] IDENTITY (1, 1) NOT NULL ,
[CategoryName] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,
[FatherID] [int] NULL
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Forms] (
[FormID] [int] IDENTITY (1, 1) NOT NULL ,
[FormName] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
[FormUrl] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
[Form_category_id] [int] NULL ,
[target] [char] (10) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
GO
CREATE FUNCTION IsLeaf (@cat_id int)
RETURNS int AS
BEGIN

declare @count int
select @count = (select count(*) from Category where FatherID=@cat_id)
if (@count=0)
return 1
return 0

END
2006/12/26

Ajax DataGrid

Ajax 实现DataGrid邦定

1. 在引用中添加引用Ajax.dll
 
2.在web.config中建立HttpHandler(这个当然是在system.web串里的)
 
<httpHandlers>
<add verb="POST,GET" path="ajax/*.ashx" type="Ajax.PageHandlerFactory, Ajax" />
</httpHandlers>
 
3.在Global的Application_Start里加上个设置
 
protected void Application_Start(Object sender, EventArgs e)
{
 Ajax.Utility.HandlerPath = "ajax";
}
 
4.新建一个类DemoMethods,这个类里面提供了更新数据库和输出列表的方法。其实主要思想就是获得控件运行后生成的html,然后输出
 
[Ajax.AjaxMethod]
public int AddAjaxTable(string name)
{
  //输入一个字符串,然后更新
  SqlConnection conn = new SqlConnection( System.Configuration.ConfigurationSettings.AppSettings["connectionString"] );
  SqlCommand cmd = new SqlCommand("insert into ajaxTable(name) values(’"+name+"’)", conn);
  cmd.Connection.Open();
  int result = cmd.ExecuteNonQuery();
  conn.Dispose();
  cmd.Dispose();
  return result;
 }

 [Ajax.AjaxMethod]
 public string GetAjaxTable()
 {
  //这个方法就是拿到datagrid生成出来的html
  SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationSettings.AppSettings["connectionString"]);
  SqlCommand cmd = new SqlCommand("select * from ajaxTable order by id", conn);
  SqlDataAdapter ap = new SqlDataAdapter( cmd );
  DataSet ds = new DataSet();
  ap.SelectCommand.Connection.Open();
  ap.Fill( ds, "db" );

  conn.Dispose();
  cmd.Dispose();

  //实例化一个datagird类并设置好数据源
  DataGrid dg = new DataGrid();
  dg.DataSource = ds.Tables["db"];1 
    dg.DataBind();

  //实例化一个HtmlTextWriter的类
  System.Text.StringBuilder strb = new System.Text.StringBuilder();
  System.IO.StringWriter sw = new System.IO.StringWriter( strb );
  System.Web.UI.HtmlTextWriter htw = new HtmlTextWriter( sw );

  //执行控件的render并输出到HtmlTextWriter里
  dg.RenderControl( htw );

  string s = strb.ToString();

  return s;//最后就是返回这个html啦
 }
 
5.然后再建一个default.js文件,用作存放 js方法
 
function AddAjax(name)
{
 DemoMethods.AddAjaxTable(name);
 LoadGrid();
}
function LoadGrid()
{
 var cc=document.getElementById("UCtd");
 cc.innerHTML=DemoMethods.GetAjaxTable().value;
}
  
6.建一个default.aspx,在pageload事件里面加个注册的东西
 
private void Page_Load(object sender, System.EventArgs e)
{
 Ajax.Utility.RegisterTypeForAjax(typeof(AjaxTestPrjLib.DemoMethods));
}
  
7.最后就是default.aspx的html和js了。
 
<%@ Page language="c#" Codebehind="default.aspx.cs" AutoEventWireup="false" Inherits="AjaxTextPrjWeb._default" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
 <title>default</title>
 <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
 <meta name="CODE_LANGUAGE" Content="C#">
 <meta name="vs_defaultClientScript" content="JavaScript">
 <meta name="vs_targetSchema" content="
http://schemas.microsoft.com/intellisense/ie5">
<script language="javascript" src="default.js"></script>
</HEAD>
<body onload="LoadGrid()">
<form id="Form1" method="post" runat="server">
 <INPUT type="text" id="AddTextBox" maxlength="10"><INPUT type="button" value="添加" onclick="javascript:AddAjax(form.AddTextBox.value);">
 <table>
  <tr>
   <td id="UCtd"></td>
  </tr>
 </table>
</form>
</body>
</HTML>

ASP.NET中利用DataGrid的自定义分页功能和存储过程结合实现高效分页

ASP.NET中利用DataGrid的自定义分页功能和存储过程结合实现高效分页
 
ASP.Net中的DataGrid有内置分页功能, 但是它的默认的分页方式效率是很低的,特别是在数据量很大的时候,用它内置的分页功能几乎是不可能的事,因为它会把所有的数据从数据库读出来再进行分页, 这种只选取了一小部分而丢掉大部分的方法是不可去取的.
在最进的一个项目中因为一个管理页面要管理的数据量非常大,所以必须分页显示,并且不能用DataGrid的内置分页功能,于是自己实现分页. 下面介绍一下我在项目中用到的分页方法.
当然显示控件还是用DataGrid的, 因为数据绑定很方便^_^.
要保证不传输冗余的数据,那么必须在数据库中数据读取时实现分页, 数据库的分页操作可以放在存储过程中. 看了CSDN的一篇Blog中讲了一个百万级数据分页的存储过程的实现(http://blog.csdn.net/wellknow/posts/55167.aspx,他的这个方法可以根据不同情况进行适当的优化), 根据他的方法,这里实现一个简单的SQL语句来实现这里分页需要的存储过程。
create procedure ListProduct
(
       @PageIndex int, -- 分页后需要页的序号
       @PageSize int, -- 一页的大小
       @ConditionSQL – 查询条件的SQL语句
)
 AS … 具体代码就不写了(可以参考上面的链接).
 
具体的SQL语句如下:
SELECT TOP 100 * FROM (select * from product where productid<200000) T WHERE T.productid NOT IN
(SELECT TOP 900 productid FROM (select productid from product where productid<200000) T1 ORDER BY T1.productid asc) ORDER BY productid asc
这条语句的 从总的商品(30万)中取出productid<200000(共20万),再按每页100的大小分页,然后取出第10页.
 
Public DataTable ListProduct(int pageIndex, int pageSize)
{
       //ADO.net从数据库中取出数据的代码就略过^_^.
}
 
 
用上面的存储过程读出的数据在DataGrid里面分页, 必须把DataGrid的AllowPaging和AllowCustomPaging设置为true
protected System.Web.UI.WebControls.DataGrid ProductGrid;
ProductGrid.AllowPaging = true;
ProductGrid.AllowCustomPaging = true;
 
然后在设置要显示的一页的大小
ProductGrid.PageSize = 100; // 在显示的时候依据实际的数据显示。
设置一页大小后,如果要让DataGrid实际分出页数来,还必须设置
ProductGrid.VirtualItemCount = GetProductCount() ; // GetProductCount() 的功能是获取满足条件的产品数目, 这里的条件就是productid<200000. 设置这项属性后,那么这个DataGrid的页数就是
VirtualItemCount/PageSize, 也就是PageCount的值. 不能对PageCount直接赋值,因为他是只读的属性.
这些属性设置好后再绑定数据:
ProductGrid.DataSource = ListProduct(1, ProductGrid.PageSize); // 在Page_Load里面 pageIndex为1,记住判断IsPostBack,在IsPostBack为false时执行这些代码
ProductGrid.DataBind();
 
这样数据绑定后就可以看到具有分页模样的页面了.但是还不能真正的分页.要实现真正的分页,还必须实现下面的功能.
 
处理DataGrid的PageIndexChanged事件(处理用户新选中某页时的事件)
private void ProductGrid_PageIndexChanged(object source, System.Web.UI.WebControls.DataGridPageChangedEventArgs e)
{
     // 如果在存储过程分页功能中用1表示第一页的序号的话那么这里必须用e.NewPageIndex+1作为pageIndex(如果选择了DataGrid上页号为3的页,那么e.NewPageIndex就为2), 否则的话直接用e.NewPageIndex就可以了
     ProductGrid.DataSource = ListProduct(e.NewPageIndex+1, ProductGrid.PageSize); // 从数据库中读取新的数据
     ProductGrid.DataBind();
     // 设置当前的Page序号值, 如果不设置的话它是不会变得, 这样会给用户造成误解,以为所有页的数据相同。
     ProductGrid.CurrentPageIndex =e.NewPageIndex;
}
 
如果你处理了DataGrid的ItemCommand的事件的话,必须在ItemCommand事件处理代码前面加上这些代码:
if (e.Item.ItemType == ListItemType.Pager)
{
     return;
}
因为当PageIndexChanged事件激发,也就是用户选则了另外一页时会先激发ItemCommand事件,如果不这样处理的话,可能会遇到一些意想不到的情况(如果你确实需要的话也可以上面这段代码,不过最好实际测试一下)。
 
整个过程完成后,再次浏览页面,觉得速度真是快多了。ASP.NET中利用DataGrid的自定义分页功能和存储过程结合实现高效分页
 
运行环境:
WinXP Pro SP1, SQLServer 2000, .Net Framework 1.1

Ajax Login Sample

一、介绍一下Ajax在Asp.Net中的基本使用
    1、在工程中引入Ajax.dll文件。
  Ajax.dll实现XmlHttpRequest请求服务器的实现细节。.net项目中,添加上对其的引用,就可以进
行相应封装操作了。
    2、在web.config中设置HttpHandle
    <httpHandlers>
      <add verb="POST,GET" path="ajax/*.ashx" type="Ajax.PageHandlerFactory, Ajax"/>
    </httpHandlers>
    3、在 <HEAD>与</HEAD>间加入一些引用如下:
    <script src=js/Xml.js></script>
    <link href="css/myStyle.css" type="text/css" rel="stylesheet">
    <script src="/HttpForAjax/ajax/common.ashx" type="text/javascript"></script>
    <script src="/HttpForAjax/ajax/Ttyu.AjaxData,HttpForAjax.ashx" type="text/javascript"></script>
    二、介绍正题-用户登录验证
    1、前台Html:
<form id="Form1" method="post" runat="server" action="" onsubmit="login.GetLogin();return false;">  
    <TABLE id="Table1"  cellSpacing="1" cellPadding="1" width="300" border="1">
     <TR>
      <TD></TD>
      <TD><INPUT type="text"  id="txtUsername">usename</TD>
     </TR>
     <TR>
      <TD></TD>
      <TD><INPUT type="password"  id="txtPassword">pwd</TD>
     </TR>
     <TR>
      <TD></TD>
      <TD><INPUT type="submit" value="登陆"></TD>
     </TR>
    </TABLE>
  </form>
    2、引用Js文件
<SCRIPT language="javascript" src="login.js" type="text/javascript"></SCRIPT>
  <script language="javascript">
  window.onload = function()
    {
       login=new Login(testAjax);
      }
  </script>
   login.Js文件
// 提取控件值
function getValueById(pObjID){
 var obj=document.getElementById(pObjID);
 try{
  return obj.value;
 }catch(e){
  alert("控件:"+pObjID+" 不存在,或没有value属性");
 }
}
function Login(obj)
{
 this.OBJ = obj;
 this.GetLogin=function()
 {
  var returnValue;
  var username=getValueById('txtUsername');
  var password=getValueById('txtPassword');
  if(!username||!password)
  {
   alert('请输入用户名与密码!');
   return;
  } 
  try
  {
   returnValue=this.OBJ.Login(username,password).value;
  }catch(e)
  {
   alert('登录出错,请稍后再试或与管理员联系');
  }
  switch(returnValue)
  {
  
   case 1:
    alert('对不起,您输入的用户名或密码不正确或者不是管理员!');
    break;  
   case 0:
    alert('管理员登录成功!');
    window.document.location.href('../Error.aspx');
    break;  
   default:
    alert('登录失败,请稍后再试或与管理员联系'+returnValue);
    break;
  }
 }
}
3、.cs文件
private void Page_Load(object sender, System.EventArgs e)
  {
   Ajax.Utility.RegisterTypeForAjax(typeof(testAjax));
  }
  [Ajax.AjaxMethod()]
  public int Login(string username,string password)
  {  
   // 管理员登陆入口
   Action.Common.CDB cdb = new Action.Common.CDB();
   if("admin"==cdb.ExeScalar("select upower from users where
uname='"+username+"' and upwd='"+password+"'"))
    return 0;
   else
    return 1;
  }
 

Ajax Shopping Cart(2)

[CS]
 
using System;
using System.Data;
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;
using AW.Components;
using AjaxPro;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using AW.Components.Helpers;
public partial class _Default : System.Web.UI.Page {
    protected string Key = "ORDERDETAIL_" + CContext.Current.SiteOwnerUserID.ToString();
    protected void Page_Load(object sender, EventArgs e) {
        Utility.RegisterTypeForAjax(typeof(_Default));
        string action = Request["Act"];
        int id;
        if (string.IsNullOrEmpty(action))
            action = "list";
        if (int.TryParse(Request["ID"], out id)) {
            if (action == "add") {
                CProduct prodcut = CProducts.GetProduct(id, CContext.Current.SiteOwnerUserID);
                if (prodcut == null) {
                    CJS.AlertAndGoUrl("此商品已经被删除!", Request.Url.AbsolutePath);
                    return;
                }
                AddProductToOrder(id, 1);
                Response.Redirect(Request.Url.AbsolutePath, true);
                return;
            }
        }
        rptView.DataSource = GetOrders();
        rptView.DataBind();
        MultiView1.ActiveViewIndex = 0;
    }
    public List<ORDERDETAIL> GetOrders() {
        HttpCookie cookie;
        cookie = Request.Cookies[Key] == null ? new HttpCookie(Key) : Request.Cookies[Key];
        NameValueCollection nvc = CHttpHelper.Base64Decode(cookie.Value);
        List<ORDERDETAIL> orders = new List<ORDERDETAIL>();
        int totalNum = 0;
        double totalMoney = 0.00;
        double totalVipMoney = 0.00;
        for (int i = 0; i < nvc.Count; i++) {
            ORDERDETAIL ord = new ORDERDETAIL(int.Parse(nvc.Keys[i]), int.Parse(nvc[i]));
            orders.Add(ord);
            totalNum += int.Parse(nvc[i]);
            totalMoney += (ord.Number * (ord.Product==null?0:ord.Product.Price));
            totalVipMoney += (ord.Number * (ord.Product==null?0:ord.Product.VipPrice));
        }
        lbTotalNum.Text = totalNum.ToString();
        lbTotalMoney.Text = totalVipMoney.ToString("0.00");
        lbDiscount.Text = (totalMoney - totalVipMoney).ToString("0.00");
        return orders;
    }
    public void AddProductToOrder(int pID, int num) {
        HttpCookie cookie;
        cookie = Request.Cookies[Key] == null ? new HttpCookie(Key) : Request.Cookies[Key];
        cookie.Path = Request.ApplicationPath;
        cookie.Domain = "." + Request.Url.Host;
        NameValueCollection nvc = CHttpHelper.Base64Decode(cookie.Value);
        if (nvc[pID.ToString()] != null)
            nvc[pID.ToString()] = (int.Parse(nvc[pID.ToString()]) + num).ToString();
        else
            nvc.Add(pID.ToString(), num.ToString());
        cookie.Value = CHttpHelper.Base64Encode(nvc);
        Response.AppendCookie(cookie);
    }
    [AjaxMethod]
    public RESUTLINFO ModifyProductNumber(int pID, int num, string cookieStr) {
        NameValueCollection nvc = CHttpHelper.Base64Decode(cookieStr);
        nvc[pID.ToString()] = num.ToString();
        return new RESUTLINFO(pID, int.Parse(nvc[pID.ToString()]),CHttpHelper.Base64Encode(nvc));
    }
    [AjaxMethod]
    public RESUTLINFO RemoveProductFromOrder(int pID, string cookieStr) {
        NameValueCollection nvc = CHttpHelper.Base64Decode(cookieStr);
        nvc.Remove(pID.ToString());
        return new RESUTLINFO(pID, CHttpHelper.Base64Encode(nvc));
    }
}
 
CS文件代码
 
[CHttpHeler]
 
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;
using System.Web;
namespace AW.Components.Helpers {
    public class CHttpHelper {
        private CHttpHelper() { }
        GetString#region GetString
        public static string GetString(NameValueCollection nvc) {
            string rtn = string.Empty;
            for (int i = 0; i < nvc.Count; i++) {
                rtn += nvc.Keys[i] + "=" + nvc[i];
                if (i < nvc.Count - 1) rtn += "&";
            }
            return rtn;
        }
        public static string GetString(string base64String) {
            byte[] bytes = Convert.FromBase64String(base64String);
            return Encoding.Default.GetString(bytes);
        }
        #endregion
        public static string Base64Encode(NameValueCollection nvc) {
            return Convert.ToBase64String(Encoding.Default.GetBytes(GetString(nvc)), Base64FormattingOptions.None);
        }
        public static NameValueCollection Base64Decode(string base64String) {
            if (string.IsNullOrEmpty(base64String))
                return new NameValueCollection();
            return HttpUtility.ParseQueryString(GetString(HttpUtility.UrlDecode(base64String)));
        }
    }
    public struct ORDERDETAIL {
        public ORDERDETAIL(int pID, int num) {
            Product = CProducts.GetProduct(pID, CContext.Current.SiteOwnerUserID);
            Number = num;
        }
        public CProduct Product;
        public int Number;
        public void ParseFromString(string str) {
        }
        public int ProudctID {
            get {
                return Product == null ? 0 : Product.ID;
            }
        }
        public override string ToString() {
            return ProudctID + ":" + Number.ToString();
        }
    }
    public struct RESUTLINFO {
        public string NVC;
        public int PID;
        public int TOTAL;
        public RESUTLINFO(int pID, string nvc) {
            PID = pID;
            NVC = nvc;
            TOTAL = 0;
        }
        public RESUTLINFO(int pID, int total, string nvc) {
            PID = pID;
            NVC = nvc;
            TOTAL = total;
        }
    }
}
一个Helper 类

Ajax Shopping Cart(1)

[ASPX]
 
<%@ Page Language="C#" MasterPageFile="~/Scripts/ShopCart/ShopCart.master" AutoEventWireup="true"
    CodeFile="Default.aspx.cs" Inherits="_Default" Title="购物车" %>
  
   <%@ Import Namespace="AW.Components.Helpers" %> 
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
    <asp:MultiView ID="MultiView1" runat="server">
        <asp:View ID="View1" runat="server">
            <script language="javascript" type="text/javascript" src='<%= this.ResolveUrl("~/Utility/Functions.js") %>'></script>
            <script language="javascript" type="text/javascript">
        var key = '<%= Key %>';
        function remove(pID){
            var v = getCookie(key)==null?"":getCookie(key);
            _Default.RemoveProductFromOrder(pID,v,remove_Callback);
        }
        function remove_Callback(res){
            if(res.error!=null)alert(res.error);
            else{
               var tr = document.getElementById("tr_" + res.value.PID.toString());
               tr.style.display = "none";        
               deleteCookie(key,"/","." + location.host);
               setCookie(key,res.value.NVC,null,"/","."+location.host);
               calcMoney();
            }
        }
        function modify(pID,num){
            var v = getCookie(key)==null?"":getCookie(key);
            _Default.ModifyProductNumber(pID,num,v,modify_Callback);
        }
        function modify_Callback(res){
            deleteCookie(key,"/","." + location.host);
            setCookie(key,res.value.NVC,null,"/","."+location.host);   
            var total = document.getElementById("txtSubTotal_" + res.value.PID.toString());
            var price = document.getElementById("txtVipPrice_" + res.value.PID.toString());
            total.value = Round(parseFloat(parseInt(res.value.TOTAL) * parseFloat(price.value)),2);
            calcMoney();
        }
        function modifyAll(){
      
        }
        function clearCart(){
            if (!confirm('确定要清空购物车吗?')) return;
            var tb = document.getElementById("tbOrder");
               for(var i=1;i<tb.rows.length;i++){
                    var tr = tb.rows.item(i);
                    if(tr.id.indexOf("_")!=-1 && tr.style.display!="none"){
                        tr.style.display = 'none';
                     }
                } 
             deleteCookie(key,"/","." + location.host);
            var ctlTotalNum = document.getElementById("<%=lbTotalNum.ClientID %>");
            var ctlTotalMoney = document.getElementById("<%=lbTotalMoney.ClientID %>");
            var ctlDiscount = document.getElementById("<%=lbDiscount.ClientID %>");    
            ctlTotalNum.innerHTML = "0";           
            ctlTotalMoney.innerHTML = "0";
            ctlDiscount.innerHTML = "0";
        }
       
        function calcMoney(){
            var ctlNums = document.getElementsByName("txtNumber");
            var ctlPrices = document.getElementsByName("txtPrice");
            var ctlVipPrices = document.getElementsByName("txtVipPrice");
            var ctlSubTotal = document.getElementsByName("txtSubTotal");
            var ctlTotalNum = document.getElementById("<%=lbTotalNum.ClientID %>");
            var ctlTotalMoney = document.getElementById("<%=lbTotalMoney.ClientID %>");
            var ctlDiscount = document.getElementById("<%=lbDiscount.ClientID %>");    
            var totalNum = 0;
            var subTotal = 0;
            var subTotalVip = 0;
            var totalMoney = 0; 
            var totalVipMoney = 0;
           
            for(var i=0;i<ctlNums.length;i++){
                totalNum += parseInt(ctlNums[i].value);
                subTotal  = parseFloat(totalNum * parseFloat(ctlPrices[i].value));
                subTotalVip =  parseFloat(totalNum * parseFloat(ctlVipPrices[i].value));
                totalMoney +=  subTotal;
                totalVipMoney += subTotalVip;
               ctlSubTotal.value = subTotalVip.toString();
            }
            ctlTotalNum.innerHTML = Round(totalNum,2);
            ctlTotalMoney.innerHTML = Round(totalVipMoney,2);
            ctlDiscount.innerHTML = Round((totalMoney - totalVipMoney),2);
        }
        function Round(a_Num , a_Bit){
            return (Math.round(a_Num * Math.pow (10 , a_Bit)) / Math.pow(10 , a_Bit)).toString()  ;
        }
        </script>
            <div id="shopcart">
                <table width="778" border="0" align="center" cellpadding="0" cellspacing="0" background="../../Icon/ShopCart/shopC_syp_5.gif">
                    <tbody>
                        <tr>
                            <td width="12">
                                <img height="72" src="../../Icon/ShopCart/shopC_syp_1.gif" width="12" /></td>
                            <td>
                                <img height="72" src="../../Icon/ShopCart/shopC_6.gif" width="176" /></td>
                            <td valign="bottom" align="right">
                                <img height="29" src="../../Icon/ShopCart/shopC_4.gif" width="324" /></td>
                            <td width="10" align="right" valign="bottom">
                                <img height="72" src="../../Icon/ShopCart/shopC_syp_3.gif" width="10" /></td>
                        </tr>
                    </tbody>
                </table>
                <table class="meun_bg" cellspacing="0" cellpadding="0" width="540" align="center"
                    border="0">
                    <tbody>
                        <tr>
                            <td align="right">
                                <img height="28" src="../../Icon/ShopCart/shopC_syx_01.gif" width="93" border="0" /></td>
                            <td>
                                <img height="32" src="../../Icon/ShopCart/shopC_sy_8.gif" width="55" /></td>
                            <td>
                                <img height="28" src="../../Icon/ShopCart/shopC_syx_02.gif" width="112" border="0" /></td>
                            <td>
                                <img height="32" src="../../Icon/ShopCart/shopC_sy_8.gif" width="55" /></td>
                            <td>
                                <img height="22" src="../../Icon/ShopCart/shopC_syx_03.gif" width="109" border="0" /></td>
                        </tr>
                    </tbody>
                </table>
                <table cellspacing="0" cellpadding="0" width="778" align="center" bgcolor="#fafafa"
                    border="0">
                    <tbody>
                        <tr>
                            <td>
                                <img height="41" hspace="8" src="../../Icon/ShopCart/shopc_z1.gif" width="143" /></td>
                        </tr>
                        <tr>
                            <td>
                                <table cellspacing="0" cellpadding="0" width="96%" align="center" border="0">
                                    <tbody>
                                        <tr align="right" bgcolor="#fafafa">
                                            <td>
                                                <img height="15" src="../../Icon/ShopCart/shopc_syx_j.gif" width="771" /></td>
                                        </tr>
                                        <tr align="right" bgcolor="#fafafa">
                                            <td class="boder_center_bg">
                                                <table cellspacing="1" width="95%" align="center" border="0" id="tbOrder">
                                                    <tbody>
                                                        <tr class="boder_topbg" align="center">
                                                            <td>
                                                                商品名称</td>
                                                            <td>
                                                                单 位</td>
                                                            <td>
                                                                数 量</td>
                                                            <td>
                                                                市场价(元)</td>
                                                            <td>
                                                                会员价(元)</td>
                                                            <td>
                                                                小 计(元)</td>
                                                            <td width="8%">
                                                                操作</td>
                                                        </tr>
                                                        <asp:Repeater ID="rptView" runat="server">
                                                            <ItemTemplate>
                                                                <tr align="center" bgcolor="#f9f9f9" id="tr_<%# ((ORDERDETAIL)Container.DataItem).Product.ID %>">
                                                                    <td align="left">
                                                                        <asp:HyperLink Target="_blank" NavigateUrl='<%# "~/" + ((ORDERDETAIL)Container.DataItem).Product.ChannelID.ToString() + "_" + ((ORDERDETAIL)Container.DataItem).Product.ID.ToString() + ".aspx" %>'
                                                                            Text='<%# ((ORDERDETAIL)Container.DataItem).Product.Name %>' runat="server" /></td>
                                                                    <td>
                                                                        <%# String.IsNullOrEmpty(((ORDERDETAIL)Container.DataItem).Product.Unit) ? "个" : ((ORDERDETAIL)Container.DataItem).Product.Unit %>
                                                                    </td>
                                                                    <td>
                                                                        <input style="text-align: right;" onbeforepaste="clipboarddata.setdata('text',clipboarddata.getdata('text').replace(/[^\d]/g,''))"
                                                                            id="txtNum_<%# ((ORDERDETAIL)Container.DataItem).Product.ID %>" onkeyup="value=value.replace(/[^\d]/g,'');"
                                                                            onblur="if(this.value.length==0)this.value=0;modify(<%# ((ORDERDETAIL)Container.DataItem).Product.ID %>,value);"
                                                                            maxlength="2" size="4" value="<%# ((ORDERDETAIL)Container.DataItem).Number %>"
                                                                            name="txtNumber" /></td>
                                                                    <td style="padding-left: 20px" align="right">
                                                                        <del>
                                                                            <%# ((ORDERDETAIL)Container.DataItem).Product.Price %>
                                                                        </del>
                                                                        <input name='txtPrice' id="txtPrice_<%# ((ORDERDETAIL)Container.DataItem).Product.ID %>"
                                                                            type="hidden" value='<%# ((ORDERDETAIL)Container.DataItem).Product.Price %>' />
                                                                    </td>
                                                                    <td style="padding-left: 20px" align="right">
                                                                        <input style="text-align: right;" name='txtVipPrice' id="txtVipPrice_<%# ((ORDERDETAIL)Container.DataItem).Product.ID %>"
                                                                            type="hidden" value='<%# ((ORDERDETAIL)Container.DataItem).Product.VipPrice %>' />
                                                                        <%# ((ORDERDETAIL)Container.DataItem).Product.VipPrice %>
                                                                    </td>
                                                                    <td style="padding-left: 20px" align="right">
                                                                        <input style="text-align: right;border: none 0px white; background-color: White;" size="4" name='txtSubTotal' id="txtSubTotal_<%# ((ORDERDETAIL)Container.DataItem).Product.ID %>"
                                                                            type="text" readonly="readonly" value='<%# ((ORDERDETAIL)Container.DataItem).Product.VipPrice * ((ORDERDETAIL)Container.DataItem).Number %>' /></td>
                                                                    <td>
                                                                        <a href="javascript:remove(<%# ((ORDERDETAIL)Container.DataItem).Product.ID %>);"><font
                                                                            color="#ff0000">删除</font></a></td>
                                                                </tr>
                                                            </ItemTemplate>
                                                        </asp:Repeater>
                                                        <tr align="right" bgcolor="#f9f9f9">
                                                            <td colspan="7">
                                                                购物车中共有
                                                                <asp:Label ID="lbTotalNum" ForeColor="red" runat="server" />
                                                                件商品,
共计 <font class="font_red">¥<asp:Label ID="lbTotalMoney" runat="server" />
                                                                    元</font>(不包括邮费) &nbsp;您节省了<font class="font_red">¥<asp:Label ID="lbDiscount" runat="server" /></font>
                                                            </td>
                                                        </tr>
                                                        <tr align="left" bgcolor="#f9f9f9">
                                                            <td colspan="7">
                                                                <img style="width: 104px; height: 27px; cursor: pointer;" onclick="modifyAll();"
                                                                    height="23" alt="单击这里保存您所修改的商品数量" width="85" src="../../Icon/ShopCart/shopc_13_02.gif"
                                                                    border="0" />
                                                                &nbsp;
                                                                <img style="cursor: pointer" onclick="clearCart();" height="27" alt="单击这里清空所有购买的商品"
                                                                    src="../../Icon/ShopCart/shopc_13_03.gif" width="104" />&nbsp;</td>
                                                        </tr>
                                                    </tbody>
                                                </table>
                                            </td>
                                        </tr>
                                        <tr align="right" bgcolor="#fafafa">
                                            <td>
                                                <img height="15" src="../../Icon/ShopCart/shopc_20.gif" width="771" /></td>
                                        </tr>
                                    </tbody>
                                </table>
                            </td>
                        </tr>
                        <tr>
                            <td align="right">
                                <img style="cursor: hand" onclick="javascript:window.close();" height="42" alt="点击继续购买您喜欢的其它商品"
                                    src="../../Icon/ShopCart/shopc_13_01.gif" width="143" vspace="10" />&nbsp; &nbsp;
                                &nbsp;
                                <img style="cursor: hand" onclick="location.href='./ClientInfo.aspx';" height="42"
                                    alt="点击去收银台结帐" hspace="10" src="../../Icon/ShopCart/shopc_13.gif" width="143"
                                    vspace="10" id="IMG1" /></td>
                        </tr>
                        <tr>
                            <td class="style2" align="center">
                            </td>
                        </tr>
                    </tbody>
                    <tr>
                        <td>
                        </td>
                    </tr>
                </table>
            </div>
        </asp:View>
    </asp:MultiView>
    <br />
    <br />
</asp:Content>
 
HTML代码 

ASP.NET Cache

ASP.NET 数据库缓存依赖

By Peter A. Bromberg, Ph.D.
在ASP.NET中,Cache类最酷的特点是它能根据各种依赖来良好的控制自己的行为。以文件为基础的依赖是最有用的,文件依赖项是通过使用 Cache.Insert 并提供引用文件的 CacheDependency 对象添加的
 
Cache.Insert("MyData", Source, new CacheDependency(Server.MapPath("authors.xml")));
 
但是当我们想让缓存根据数据库中表的变化而失效并重建该缓存的时候,应该怎么做呢 – 这种情景在很多应用程序中都存在。Asp.net没有为监视数据库表的变化提供内在的直接缓存支持。利用SQL Server的不常用的系统存储过程sp_makewebtask ,是可以达到这个目的的,这个存储过程本来是用作从查询中生成web页面的,但是我们只要稍作修改- 在触发器中使用它,我们就可以取得一个合理有效的途径,当数据库某张表的记录被更新,删除或者修改时来修改某个特定的文件, 这样会使在CacheDependency实例中的文件监视进程侦测到文件的变化,从而使缓存失效。事实上,因为CacheDependency 类工作在UNC文件协议上,我们可以在整个Web Farm上部署这个解决方案,Web Farm上每台机器上的应用程序副本都会通过UNC文件路径来监视WebFarm中某台单个机器上的同一个文件
废话少说,让我们创建一个简单的web应用程序,来演示它是如果工作的。首先,我们将会使用我们SQL Server中都信赖的Northwind范例数据库。创建一个简单的DataGrid来显示Employees表中的记录. 我们要做的第一件事情就是创建触发器。
CREATE TRIGGER WriteCacheDepFile ON [dbo].[Employees]
FOR INSERT, UPDATE, DELETE
AS
EXEC sp_makewebtask '\\peter\C$\Cache\mycache.txt', 'SELECT top 1 FirstName FROM employees'
 
以上存储过程就是简单的告诉SQL Server,如果Employee表发生任何变动,就根据一个简单的查询来更新”mycache.txt”文件,有这个简单的查询语句其实足够了,只要它是一个有效的T-SQL语句,SQL Server会很乐意的去更新那个文件。
接下来,我们需要创建一个目录,并设为共享。你可能要更新该文件的访问权限,以使它可以被写入,注意,我这里使用的是管理员共享”C$”.另外,你还需要创建一个空的文本文件,"mycache.txt".
好,现在可以创建我们的应用程序了。首先,在web.config文件中输入依赖文件名称,这样做可以使我们在修改依赖文件的时候不需要重新部署应用程序。
在web.config文件的根部,添加appSettings配置节:
</system.web>
<appSettings>
<!—缓存依赖文件路径 -->
<add key="dependencyFile" value="\\peter\Cache\mycache.txt" />
</appSettings>
</configuration>
 
现在,让我们在Global类中建立缓存机制,这样我们不需要在任何页面中编写特定的代码

[C#]
public class Global : System.Web.HttpApplication
{
Cache _cache =null;
public static bool blnReflash = false;
public const string ConnStr = "server=localhost;database=Northwind;uid=sa;pwd=";
public const string strSQL = "SELECT EmployeeID, lastname, firstname FROM Employees";
 
protected void Application_Start(Object sender, EventArgs e)
{
_cache = Context.Cache;
RefreshCahe(null,null,0);
}
 
protected void Session_Start(Object sender, EventArgs e)
{
if(HttpContext.Current.Cache["Employees"]==null)
RefreshCache(null,null,0);
}
 
static void RefreshCache(string key,object item,CacheItemRemoveReason reason)
{
SqlDataAdapter adapter = new SqlDataAdapter(strSQL,ConnStr);
DataSet ds = new DataSet();
adapter.Fill(ds,"Employees");
CacheItemRemovedCallback onRemove = new CacheItemRemovedCallback(RefreshCache);
 
string depFile= ConfigurationSettings.AppSettings["dependencyFile"].ToString();
HttpContext.Current.Cache.Insert("Employees",ds,new CacheDependency(depFile),
Cache.NoAbsoluteExpiration,Cache.NoSlidingExpiration,
CacheItemPriority.High,onRemove);
 
blnReflash = true;
}
 
就像上面看到的一样,我们定义了一个Cache类型的_cache对象,在Application_Start方法中,我们把当前的Cache实例赋给它,然后调用RefreshCache方法去填充该对象。RefreshCache实际上是一个静态的委托回调方法,它所做的就是简单的从Empoyees表中取得一个DataSet,然后创建CacheItemRemovedCallback类型的委托OnRemove,使其指向RefreshCache方法,这样当被监控的文件变化时,也就是缓存失效时,就会调用该委托,刷新缓存中的数据。
最后我们把DataSet连同OnRemove委托一起插入到缓存中,在Session_Start中,为了“保险“,我另外添加了一个判断来调用RefreshCache方法填充缓存。
到这里,我们应用程序就创建好了,在任何页面中都可以访问到缓存的DataSet。在WebForm1aspx中,我演示了如何使用它。
[C#]
private void Page_Load(object sender, System.EventArgs e)
{
//保证缓存非空,如果为空,则填充它
if(Cache["Employees"] == null)
Global.RefreshCache(null,null, 0);
cacheStatus.Text = "Cache Refreshed at "+ DateTime.Now.ToLongTimeString();
else
cacheStatus.Text = " DataSet from Cache ";
 
DataSet ds = (DataSet)Cache["Employees"];
DataGrid1.DataSource= ds.Tables[0];
DataGrid1.DataBind();
}
 
现在,如果你请求这个页面,它将会每次成功的显示从从Cache中取得

ASP.NET 2.0 SQL Cache

Stephen Walther
  
  Microsoft Corporation
  
  适用于:
  
  Microsoft ASP.NET 2.0
  
  Microsoft ASP.NET Framework
  
  Microsoft SQL Server
  
  Microsoft Visual Studio .NET
  
  摘要:本文中,Stephen Walther 将重点介绍 ASP.NET 2.0 中新增的缓存功能,以及如何使用这些新功能改进 ASP.NET 应用程序的性能和可扩展性。(本文包含一些指向英文站点的链接。)
  
  
  
  本页内容
   更轻松的数据缓存
   使用 SQL Cache Invalidation
   使用 Post-Cache Substitution
   结论
  
  对于由数据库驱动的 Web 应用程序来说,要改进其性能,最好的方法就是使用缓存。从数据库中检索数据可能是您在 Web 站点上执行的最慢的操作之一。如果能够将数据库中的数据缓存到内存中,就无需在请求每个页面时都访问数据库,从而可以大大提高应用程序的性能。
  
  缓存有一个且只有一个缺点,那就是数据过期的问题。如果将数据库表的内容缓存到内存中,当基础数据库表中的记录发生更改时,您的 Web 应用程序将显示过期的、不准确的数据。对于某些类型的数据,即便显示的数据稍微有些过期,影响也不会太大;但对于诸如股票价格和竞拍出价之类的数据,即使显示的数据稍微有些过期也是不可接受的。
  
  Microsoft ASP.NET 1.0 Framework 没有针对此问题提供一个完善的解决方案。使用 ASP.NET 1.0 Framework 时,您不得不在性能和数据过期之间作出权衡。幸运的是,Microsoft ASP.NET 2.0 Framework 提供了一项新功能,称为 SQL Cache Invalidation,可以解决这一棘手的问题。
  
  在本文中,您将进一步了解 ASP.NET 2.0 Framework 中许多新的缓存改进功能。首先,您将了解到如何在新增的 DataSource 控件中集成缓存支持。然后,您将了解到如何配置和使用 SQL Cache Invalidation。最后,您将了解到随 ASP.NET 2.0 Framework 引入的一个新控件:Substitution 控件,使用该控件可以向已缓存的页面中插入动态内容。
  
  更轻松的数据缓存
  在 ASP.NET 2.0 Framework 中,最大的变化之一就是在 ASP.NET 页面上访问数据库数据的方式发生了变化。ASP.NET 2.0 Framework 包含一组新的控件,统称为 DataSource 控件。您可以使用这些控件来表示数据源,例如数据库或 XML 文件。
  
  在 ASP.NET 1.0 Framework 中,是通过将控件绑定到 DataSet 或 DataReader,使用控件来显示数据库数据的。而在 ASP.NET 2.0 Framework 中,通常是将控件绑定到 DataSource 控件。通过 DataSource 控件,您可以创建显示数据库数据的 ASP.NET 页面,而不用为访问数据库编写任何代码。
  
  在处理数据库数据时,通常使用下列三个 DataSource 控件中的一个控件:
  
  • SqlDataSource — 表示 SQL 数据源,例如 Microsoft SQL Server 或 Oracle 数据库。
  
  • AccessDataSource — 一个专用的 SqlDataSource 控件,用于 Microsoft Access 数据库。
  
  • ObjectDataSource — 表示充当数据源的自定义业务对象。
  
  
  例如,假设您要在 DropDownList 控件中显示从数据库中检索到的书目列表(参见图 1)。列表 1 中的页面说明了如何将 DropDownList 控件绑定到 SqlDataSource 控件。
  
  图 1:使用 SqlDataSource 控件检索数据
  
  
  列表 1:DisplayTitles.aspx
  
  <html>
  <head runat ="server">
  <title>Display Titles</title>
  </head>
  <body>
  <form id="form1" runat ="server">
  
  <asp:DropDownList
  ID="DropDownList1"
  DataSourceId="SqlDataSource1"
  DataTextField="Title"
  Runat="server" />
  
  <asp:SqlDataSource
  ID="SqlDataSource1"
  ConnectionString="Server=localhost;database=Pubs"
  SelectCommand="SELECT Title FROM Titles"
  Runat="server" />
  
  </form>
  </body>
  </html>
  
  请注意,列表 1 中的 SqlDataSource 控件用于提供连接字符串,SQL SELECT 命令用于从数据库中检索记录。DropDownList 控件通过其 DataSourceID 属性绑定到 SqlDataSource 控件。
  
  使用 DataSource 控件缓存数据
  使用 DataSource 控件,不仅可以更轻松地连接数据库,还使缓存数据库数据变得更容易。只需在 SqlDataSource 控件上设置一两个属性,就可以自动在内存中缓存由 DataSource 控件表示的数据。
  
  例如,如果要将 Titles 数据库表在内存中缓存至少 10 分钟,可以按照以下方式声明 SqlDataSource 控件。
  
   <asp:SqlDataSource
  ID="SqlDataSource1"
  EnableCaching="true"
  CacheDuration="600"
  ConnectionString="Server=localhost;database=Pubs"
  SelectCommand="SELECT Title FROM Titles"
  Runat="server" />
  
  如果 EnableCaching 属性的值为 true,SqlDataSource 将自动缓存通过 SelectCommand 检索到的数据。使用 CacheDuration 属性,可以指定从数据库中刷新数据之前缓存数据的时间(以秒为单位)。
  
  默认情况下,SqlDataSource 使用绝对过期策略来缓存数据,即每隔指定的秒数就从数据库中刷新一次。此外,您还可以选择使用可变过期策略。如果将 SqlDataSource 配置为使用可变过期策略,那么只要持续访问数据,数据就不会过期。如果需要缓存大量项目,使用可变过期策略将非常有用,因为这种过期策略将只在内存中保留访问最频繁的项目。
  
  例如,下面的 SqlDataSourceControl 被配置为使用可变过期策略,过期时间为 10 分钟。
  
  <asp:SqlDataSource
  ID="SqlDataSource1"
  EnableCaching="true"
  CacheExpirationPolicy="Sliding"
  CacheDuration="600"
  ConnectionString="Server=localhost;database=Pubs"
  SelectCommand="SELECT Title FROM Titles"
  Runat="server" />
  
  由于 CacheExpirationPolicy 属性的值被设置为 Sliding,CacheDuration 属性的值被设置为 600,因此,只要在 10 分钟内持续访问,此 SqlDataSource 表示的数据就会一直保留在内存中。
  
  返回页首
  使用 SQL Cache Invalidation
  SQL Cache Invalidation 是 ASP.NET 2.0 Framework 最值得期待的新增功能之一。使用 SQL Cache Invalidation 可以获得缓存的全部性能优势,而不用担心数据过期的问题。SQL Cache Invalidation 使您可以在基础数据库中的数据发生更改时自动更新缓存中的数据。
  
  SQL Cache Invalidation 通过在后台不断轮询数据库来检查数据更改。每隔一定的时间(毫秒),ASP.NET Framework 就会检查数据库中是否存在更新。如果 ASP.NET Framework 检测到任何更改,将从缓存中删除从数据库中添加的、依赖于数据库的任何项目(即,这些项目将过期)。
  
  注意:Microsoft SQL Server 2005 支持一种截然不同的 SQL Cache Invalidation 方法。您可以配置 SQL Server 2005,使其在数据库、数据库表或数据库行发生变化时通知 ASP.NET 应用程序。这样,ASP.NET Framework 就不需要通过不断轮询 SQL Server 2005 数据库来检查数据更改了。
  
  需要注意的是,SQL Cache Invalidation 只能用于 Microsoft SQL Server 7 及更高版本,不能用于其他数据库,例如 Microsoft Access 或 Oracle。
  
  在缓存整个页面的输出、使用 DataSource控件或直接使用 Cache 对象时,都可以使用 SQL Cache Invalidation。下面将分别介绍这三种情况。
  
  配置 SQL Cache Invalidation
  在 Web 应用程序中使用 SQL Cache Invalidation 之前,首先必须执行一些配置步骤。必须将 Microsoft SQL Server 配置为支持 SQL Cache Invalidation,还必须在应用程序的 Web 配置文件中添加必要的配置信息。
  
  可以按照以下两种方法配置 SQL Server:使用 aspnet_regsql 命令行工具,或者使用 SqlCacheDependencyAdmin 类。
  
  使用 ASPNET_REQSQL 启用 SQL Cache Invalidation
  使用 aspnet_regsql 工具,您可以通过命令行来配置 SQL Cache Invalidation。aspnet_regsql 工具位于 Windows\Microsoft.NET\Framework\[版本] 文件夹中。要使用此工具,必须打开命令提示符窗口并浏览到此文件夹。
  
  要在使用 Pubs 数据库时支持 SQL Cache Invalidation,需要执行以下命令。
  
  aspnet_regsql -E -d Pubs -ed
  
  -E 选项使 aspnet_regsql 工具在连接到数据库服务器时使用集成的安全设置。-d 选项用于选择 Pubs 数据库。最后,-ed 选项用于为数据库启用 SQL Cache Invalidation。
  
  执行此命令时,将在数据库中添加一个名为 AspNet_SqlCacheTablesForChangeNotification 的新数据库表。此表包含启用了 SQL Cache Invalidation 的所有数据库表的列表。此命令还将在数据库中添加一组存储过程。
  
  为数据库启用 SQL Cache Invalidation 后,必须从数据库中选择要启用 SQL Cache Invalidation 的特定表。以下命令将为 Titles 数据库表启用 SQL Cache Invalidation。
  
  aspnet_regsql -E -d Pubs -t Titles -et
  
  -t 选项用于选择数据库表。-et 选项为数据库表启用 SQL Cache Invalidation。当然,您可以通过对每个数据库表重复执行此命令,为多个表启用 SQL Cache Invalidation。
  
  执行此命令时,将在数据库表中添加一个触发器。只要您对表进行了修改,此触发器就将触发并更新 AspNet_SqlCacheTablesForChangeNotification 表。
  
  最后,要获取某个特定数据库中当前启用了 SQL Cache Invalidation 的表的列表,可以使用以下命令。
  
  aspnet_regsql -E -d Pubs -lt
  
  此方法将从 AspNet_SqlCacheTablesForChangeNotification 中选择表的列表。此外,您也可以通过直接在该数据库表中执行查询来检索此信息。
  
  使用 SqlCacheDependencyAdmin 类
  aspnet_regsql 工具在后台使用 SqlCacheDependencyAdmin 类的方法来配置 Microsoft SQL Server。如果您愿意,可以直接从 ASP.NET 页面中使用此类的方法。
  
  SqlCacheDependencyAdmin 类具有五个重要的方法:
  
  • DisableNotifications — 为特定数据库禁用 SQL Cache Invalidation。
  
  • DisableTableForNotifications — 为数据库中的特定表禁用 SQL Cache Invalidation。
  
  • EnableNotifications — 为特定数据库启用 SQL Cache Invalidation。
  
  • EnableTableForNotifications — 为数据库中的特定表启用 SQL Cache Invalidation。
  
  • GetTablesEnabledForNotifications — 返回启用了 SQL Cache Invalidation 的所有表的列表。
  
  
  例如,使用列表 2 中的 ASP.NET 页面,您可以为 Pubs 数据库中的任何表配置 SQL Cache Invalidation(参见图 2)。
  
  图 2:从 ASP.NET 页面中启用 SQL Cache Invalidation
  
  
  列表 2:EnableSCI.aspx (C#)
  
  <%@ Page Language="c#" %>
  <%@ Import Namespace="System.Web.Caching" %>
  <script runat ="server">
  
  const string connectionString = "Server=localhost;Database=Pubs";
  
  void Page_Load()
   {
  if (!IsPostBack)
   {
  SqlCacheDependencyAdmin.EnableNotifications(
  connectionString);
  SqlDataSource1.SelectParameters.Add("connectionString",
  connectionString);
   }
   }
  
  void EnableTable(Object s, EventArgs e)
   {
  try
   {
  SqlCacheDependencyAdmin.EnableTableForNotifications(
  connectionString, txtTableName.Text);
   }
  catch (Exception ex)
   {
  lblErrorMessage.Text = ex.Message;
   }
  txtTableName.Text = "";
   }
  
  </script>
  
  <html>
  <head runat ="server">
  <title>Enable SQL Cache Invalidation</title>
  </head>
  <body>
  <form id="form1" runat ="server">
  
  <h1>SQL Cache Invalidation</h1>
  
  以下表格已启用 SQL Cache Invalidation:
  
  <p>
  <asp:GridView id="grdTables"
  DataSourceID="SqlDataSource1" CellPadding="10"
  ShowHeader="false" Runat="Server" />
  </p>
  
  <asp:ObjectDataSource
  ID="SqlDataSource1"
  TypeName="System.Web.Caching.SqlCacheDependencyAdmin"
  SelectMethod="GetTablesEnabledForNotifications"
  Runat="Server" />
  <p>
  <asp:Label ID="lblErrorMessage" EnableViewState="false"
  ForeColor="red" Runat="Server" />
  </p>
  
  <asp:TextBox ID="txtTableName" Runat="Server" />
  <asp:Button Text="Enable Table" OnClick="EnableTable"
  Runat="Server" />
  
  </form>
  </body>
  </html>
  
  列表 2:EnableSCI.aspx (Visual Basic .NET)
  
  <%@ Page Language="vb" %>
  <%@ Import Namespace="System.Web.Caching" %>
  <script runat ="server">
  
  Const connectionString As String = "Server=localhost;Database=Pubs"
  
  Sub Page_Load()
  
  If Not IsPostBack Then
  SqlCacheDependencyAdmin.EnableNotifications( _
  connectionString)
  SqlDataSource1.SelectParameters.Add("connectionString", _
  connectionString)
  End If
  End Sub
  
  Sub EnableTable(ByVal s As Object, ByVal e As EventArgs)
  
  Try
  
  SqlCacheDependencyAdmin.EnableTableForNotifications( _
  connectionString, txtTableName.Text)
  Catch ex As Exception
  lblErrorMessage.Text = ex.Message
  End Try
  txtTableName.Text = ""
  End Sub
  
  </script>
  
  <html>
  <head id="Head1" runat ="server">
  <title>ConfigureSCI</title>
  </head>
  <body>
  <form id="form1" runat ="server">
  
  <h1>SQL Cache Invalidation</h1>
  
  以下表格已启用 SQL Cache Invalidation:
  
  <p>
  <asp:GridView id="grdTables" DataSourceID="SqlDataSource1"
  CellPadding="10" ShowHeader="false" Runat="Server" />
  </p>
  
  <asp:ObjectDataSource
  ID="SqlDataSource1"
  TypeName="System.Web.Caching.SqlCacheDependencyAdmin"
  SelectMethod="GetTablesEnabledForNotifications"
  Runat="Server" />
  <p>
  <asp:Label ID="lblErrorMessage" EnableViewState="false"
  ForeColor="red" Runat="Server" />
  </p>
  
  <asp:TextBox ID="txtTableName" Runat="Server" />
  <asp:Button ID="Button1" Text="Enable Table"
  OnClick="EnableTable" Runat="Server" />
  
  </form>
  </body>
  </html>
  
  在列表 2 中,connectionString 常量用于选择启用了 SQL Cache Invalidation 的数据库(如果要为 Pubs 数据库以外的数据库启用 SQL Cache Invalidation,可以更改此常量的值)。在 Page_Load 方法中,调用 SqlCacheDependencyAdmin 类上的 EnableNotifications 方法,为由 connectionString 常量指定的数据库启用 SQL Cache Invalidation。
  
  列表 2 中的 GridView 显示了当前启用了 SQL Cache Invalidation 的所有数据库表。GridView 被绑定到 ObjectDataSource 控件上,该控件为其 SelectMethod 调用 GetTablesneabledForNotifications 方法。
  
  最后,您可以使用列表 2 中的页面为其他表启用 SQL Cache Invalidation。在文本框中输入表的名称并单击“Enable Table”按钮时,将调用 EnableTableForNotifications 方法。
  
  SQL Cache Invalidation 的 Web 配置设置
  在 ASP.NET 应用程序中使用 SQL Cache Invalidation 之前,下一步要做的是更新您的 Web 配置文件。您需要配置 ASP.NET Framework,以便轮询启用了 SQL Cache Invalidation 的数据库。
  
  列表 3 中的 Web 配置文件包含轮询 Pubs 数据库所必需的配置信息。
  
  列表 3:Web.Config
  
  <configuration>
  
  <connectionStrings>
  <add name="mySqlServer"
  connectionString="Server=localhost;Database=Pubs" />
  </connectionStrings>
  
  <system.web>
  
  <caching>
  <sqlCacheDependency enabled="true">
  <databases>
  <add
  name="Pubs"
  connectionStringName="mySqlServer"
  pollTime="60000" />
  </databases>
  </sqlCacheDependency>
  </caching>
  </system.web>
  </configuration>
  
  列表 3 中的 Web 配置文件包含两部分。<connectionStrings> 部分用于创建数据库连接字符串,以连接到名为 mySqlServer 的 Pubs 数据库。
  
  caching 部分用于配置 SQL Cache Invalidation 轮询。在 <databases> 子部分中,您可以列出要对其进行轮询以检查数据更改的一个或多个数据库。在列表 3 中,mySqlServer 表示的数据库每分钟(每 60000 毫秒)轮询一次。
  
  您可以为不同的数据库指定不同的轮询间隔。每次轮询数据库以检查数据更改时,服务器都必须执行一些操作。如果您认为数据库中的数据不会频繁地更改,可以增加轮询间隔。
  
  在页面输出缓存中使用 SQL Cache Invalidation
  现在,我们已经完成了 SQL Cache Invalidation 的所有配置步骤,可以在 ASP.NET 页面中使用它了。一种方法是在页面输出缓存中使用 SQL Cache Invalidation。页面输出缓存允许您在内存中缓存页面所显示的所有内容。通过使用 SQL Cache Invalidation,您可以在(且只在)数据库表发生更改时自动更新缓存的页面。
  
  例如,列表 4 中的页面在 GridView 控件中显示了 Titles 数据库表的内容。在该页面的顶部,OutputCache 指令用于在内存中缓存页面内容。如果 Titles 数据库表发生更改,SqlDependency 属性将使页面更新。
  
  列表 4:OutputCacheTitles.aspx
  
  <%@ OutputCache SqlDependency="Pubs:Titles"
  Duration="6000" VaryByParam="none" %>
  <html>
  <head runat ="server">
  <title>Output Cache Titles</title>
  </head>
  <body>
  <form id="form1" runat ="server">
  
  <%= DateTime.Now %>
  
  <asp:GridView
  ID="grdTitles"
  DataSourceID="SqlDataSource1"
  Runat="Server" />
  
  <asp:SqlDataSource
  ID="SqlDataSource1"
  SelectCommand="Select * FROM Titles"
  ConnectionString="<%$ ConnectionStrings:mySqlServer %>"
  Runat="Server" />
  
  </form>
  </body>
  </html>
  
  请注意,SqlDependency 属性引用了 Web 配置文件中定义的数据库的名称。由于我们指定了每分钟轮询一次 Pubs 数据库以检查数据更改,因此如果对该数据库进行了更改,列表 4 中的页面将在一分钟之内进行更新。
  
  您可以为 SqlDependency 属性值列出多个数据库和/或多个数据库表。要创建多个依赖关系,只需用分号分隔每个依赖关系即可。
  
  在 DataSource 控件中使用 SQL Cache Invalidation
  除了在页面输出缓存中使用 SQL Cache Invalidation 之外,还可以直接在 DataSource 控件中使用 SQL Cache Invalidation。如果要在多个页面中使用相同的数据库数据,请考虑在 DataSource 控件中使用 SQL Cache Invalidation。SqlDataSource、AccessDataSource 和 ObjectDataSource 控件都支持 SqlCacheDependency 属性。
  
  例如,列表 5 中的页面在 SqlDataSource 控件中使用了 SQL Cache Invalidation。
  
  列表 5:SqlDataSourceCaching.aspx
  
  <html>
  <head id="Head1" runat ="server">
  <title>SqlDataSource Caching</title>
  </head>
  <body>
  <form id="form1" runat ="server">
  
  <%= DateTime.Now %>
  
  <asp:GridView
  ID="grdTitles"
  DataSourceId="SqlDataSource1"
  Runat="server" />
  
  <asp:SqlDataSource
  ID="SqlDataSource1"
  EnableCaching="true"
  SqlCacheDependency="Pubs:Titles"
  SelectCommand="select * from titles"
  ConnectionString="<%$ ConnectionStrings:mySqlServer %>"
  Runat="server" />
  
  </form>
  </body>
  </html>
  
  在列表 5 中,SqlDataSource 控件是使用 EnableCaching 和 SqlCacheDependency 这两个属性声明的。SqlCacheDependency 属性使用的语法与 OutputCache 指令的 SqlDependency 属性相同。您需要列出数据库的名称,后跟数据库表的名称。
  
  在 Cache 对象中使用 SQL Cache Invalidation
  最后,您还可以在 Cache 对象中使用 SQL Cache Invalidation。此选项使您可以最大程度地对 SQL Cache Invalidation 进行编程控制。
  
  要在 Cache 对象中使用 SQL Cache Invalidation,您需要创建一个 SqlCacheDependency 对象实例。使用 Insert 方法在 Cache 中插入新对象时,可以使用 SqlCacheDependency 对象。
  
  例如,列表 6 中的页面显示了 Titles 数据库表中的记录数。计数是基于对基础数据库表的依赖关系进行缓存的。
  
  列表 6:DisplayTitleCount.aspx (C#)
  
  <%@ Page Language="c#" %>
  <%@ Import Namespace="System.Data.SqlClient" %>
  <script runat ="server">
  
  void Page_Load()
   {
  int count = 0;
  
  if (Cache["TitleCount"] != null)
   {
  count = (int)Cache["TitleCount"];
   }
  else
   {
  string connectionString =
  ConfigurationSettings.ConnectionStrings[
  "mySqlServer"].ConnectionString;
  SqlConnection con = new SqlConnection(connectionString);
  SqlCommand cmd = new
  SqlCommand("SELECT Count(*) FROM Titles", con);
  con.Open();
  count = (int)cmd.ExecuteScalar();
  con.Close();
  Cache.Insert("TitleCount", count,
  new SqlCacheDependency("Pubs", "Titles"));
   }
  lblTitleCount.Text = count.ToString();
   }
  
  </script>
  
  <html>
  <head runat ="server">
  <title>Display Title Count</title>
  </head>
  <body>
  <form id="form1" runat ="server">
  
  <asp:Label ID="lblTitleCount" Runat="Server" />
  
  </form>
  </body>
  </html>
  
  列表 6:DisplayTitleCount.aspx (Visual Basic .NET)
  
  <%@ Page Language="vb" %>
  <%@ Import Namespace="System.Data.SqlClient" %>
  <script runat ="server">
  
  Sub Page_Load()
  
  Dim count As Integer = 0
  
  If Not Cache("TitleCount") Is Nothing Then
  count = Convert.ToInt32(Cache("TitleCount"))
  Else
  Dim connectionString As String = _
  ConfigurationSettings.ConnectionStrings( _
  "mySqlServer").ConnectionString
  Dim con As New SqlConnection(connectionString)
  Dim cmd As New _
  SqlCommand("SELECT Count(*) FROM Titles", con)
  con.Open()
  count = Convert.ToInt32(cmd.ExecuteScalar())
  con.Close()
  Cache.Insert("TitleCount", count, _
  new SqlCacheDependency("Pubs", "Titles"))
  End If
  
  lblTitleCount.Text = count.ToString()
  End Sub
  
  </script>
  
  <html>
  <head id="Head1" runat ="server">
  <title>Display Titles Count</title>
  </head>
  <body>
  <form id="form1" runat ="server">
  
  <asp:Label ID="lblTitleCount" Runat="Server" />
  
  </form>
  </body>
  </html>
  
  返回页首
  使用 Post-Cache Substitution
  在许多情况下,您需要缓存页面的一部分,而不是整个页面。例如,在您的 Web 站点主页上,您可能希望同时显示随机的标题广告和数据库表中的记录。如果缓存整个页面,每个用户都将在每次请求的页面上看到同一个标题广告。
  
  要处理这种同时混有动态内容和缓存内容的问题,一种方法是使用 Web 用户控件。因为可以为 Web 用户控件添加 OutputCache 指令,所以即使不缓存包含页面的内容,也可以缓存 Web 用户控件的内容。
  
  但有时候可能会事与愿违。虽然您可以使用 Web 用户控件在动态页面上添加缓存的内容,但很多情况下,您实际上是想在缓存的页面中添加动态内容。例如,假设您要缓存整个页面的内容,只留一小块区域用于显示当前用户的用户名。这种情况下最好使用 Post-Cache Substitution。
  
  ASP.NET 2.0 Framework 引入了一种新控件,称为 Substitution 控件。您可以使用 Substitution 控件在缓存的页面中插入动态内容。列表 7 中的页面使用 Substitution 控件将用户名插入到缓存的内容中(参见图 3)。
  
  图 3:使用 Substitution 控件显示用户名
  
  
  列表 7:PostCacheSubstitution.aspx (C#)
  
  <%@ Page Language="C#" %>
  <%@ OutputCache Duration="6000" VaryByParam="none" %>
  
  <script runat ="server">
  
  static string DisplayUsername(HttpContext context)
   {
  if (!context.Request.IsAuthenticated)
  return "Anonymous";
  else
  return context.User.Identity.Name;
   }
  
  </script>
  
  <html>
  <head runat ="server">
  <title>Post Cache Substitution</title>
  </head>
  <body>
  <form id="form1" runat ="server">
  
  Welcome <asp:Substitution
  MethodName="DisplayUsername" Runat="Server" />!
  
  <p>
  此页已缓存, 因为时间
  <%= DateTime.Now.ToString("t") %> 并无改变。
  </p>
  
  </form>
  </body>
  </html>
  
  列表 7:PostCacheSubstitution.aspx (Visual Basic .NET)
  
  <%@ Page Language="vb" %>
  <%@ OutputCache Duration="6000" VaryByParam="none" %>
  
  <script runat ="server">
  
  Shared Function DisplayUsername(ByVal context As HttpContext) _
  As String
  If Not context.Request.IsAuthenticated Then
  Return "Anonymous"
  Else
  Return context.User.Identity.Name
  End If
  End Function
  
  </script>
  
  <html>
  <head id="Head1" runat ="server">
  <title>Post Cache Substitution</title>
  </head>
  <body>
  <form id="form1" runat ="server">
  
  Welcome <asp:Substitution
  ID="Substitution1"
  MethodName="DisplayUsername"
  Runat="Server" />!
  
  <p>
  此页已缓存, 因为时间
  <%= DateTime.Now.ToString("t") %> 并无改变。
  </p>
  
  </form>
  </body>
  </html>
  
  Substitution 控件有一个非常重要的属性:即 MethodName 属性。MethodName 属性用于表示为返回动态内容而调用的方法。由 Substitution 控件调用的方法必须是静态方法(在 Visual Basic .NET 中共享的方法)。此外,该方法还必须具有一个表示当前 HttpContext 的参数。
  
  在 ASP.NET 2.0 Framework 中,已对 AdRotator 控件进行了修改以支持 Post-Cache Substitution。如果在使用 OutputCache 指令的页面中添加 AdRotator 控件,AdRotator 控件将自动从其包含页面的缓存策略中排除出去。
  
  返回页首
  结论
  缓存对由数据库驱动的 Web 应用程序的性能具有非常大的影响。幸运的是,ASP.NET 2.0 Framework 提供了许多新的重要增强功能,使您可以在应用程序中更轻松地使用缓存功能。
  
  新增的 DataSource 控件中包含的属性使得在内存中缓存数据库数据变得非常容易。通过使用 DataSource 控件,您可以检索并缓存数据库数据,而无需编写任何代码。
  
  新增的 SQL Cache Invalidation 支持使您可以在基础数据库中的数据发生更改时自动在缓存中重新加载数据库数据。此功能为您提供了缓存的所有性能优势,而不用担心数据过期的问题。
  
  最后,使用新增的 Substitution 控件,您可以更轻松地在缓存的页面中混合动态内容。Substitution 控件为您在缓存的页面中插入动态内容提供了一个独立的空间。
  
  作者简介
  
  Stephen Walther 编写了有关 ASP.NET 的畅销书 ASP.NET Unleashed。此外,他还是 ASP.NET Community Starter Kit(Microsoft 开发的 ASP.NET 示例应用程序)的体系结构设计师和主要开发人员。他还通过自己的公司 Superexpert (http://www.superexpert.com/) 为美国的公司(包括 NASA 和 Microsoft)提供 ASP.NET 培训。
2006/12/11

CSS

 一.使用css缩写
使用缩写可以帮助减少你CSS文件的大小,更加容易阅读。css缩写的主要规则请参看《常用css缩写语法总结》,这里就不展开描述。
 
二.明确定义单位,除非值为0
忘记定义尺寸的单位是CSS新手普遍的错误。在HTML中你可以只写width=100,但是在CSS中,你必须给一个准确的单位,比如:width: 100px width:100em。只有两个例外情况可以不定义单位:行高和0值。除此以外,其他值都必须紧跟单位,注意,不要在数值和单位之间加空格。
 
三.区分大小写
当在XHTML中使用CSS,CSS里定义的元素名称是区分大小写的。为了避免这种错误,我建议所有的定义名称都采用小写。
class和id的值在HTML和XHTML中也是区分大小写的,如果你一定要大小写混合写,请仔细确认你在CSS的定义和XHTML里的标签是一致的。
 
四.取消class和id前的元素限定
当你写给一个元素定义class或者id,你可以省略前面的元素限定,因为ID在一个页面里是唯一的,鴆las s可以在页面中多次使用。你限定某个元素毫无意义。例如:
div#content { /* declarations */ }
fieldset.details { /* declarations */ }
可以写成
#content { /* declarations */ }
.details { /* declarations */ }
这样可以节省一些字节。
 
五.默认值
通常padding的默认值为0,background-color的默认值是transparent。但是在不同的浏览器默认值可能不同。如果怕有冲突,可以在样式表一开始就先定义所有元素的margin和padding值都为0,象这样:
* {
margin:0;
padding:0;
}
 
六.不需要重复定义可继承的值
CSS中,子元素自动继承父元素的属性值,象颜色、字体等,已经在父元素中定义过的,在子元素中可以直接继承,不需要重复定义。但是要注意,浏览器可能用一些默认值覆盖你的定义。
 
七.最近优先原则
如果对同一个元素的定义有多种,以最接近(最小一级)的定义为最优先,例如有这么一段代码
Update: Lorem ipsum dolor set
在CSS文件中,你已经定义了元素p,又定义了一个classupdate
p {
margin:1em 0;
font-size:1em;
color:#333;
}
.update {
font-weight:bold;
color:#600;
}
这两个定义中,class=update将被使用,因为class比p更近。你可以查阅W3C的《 Calculating a selector’s specificity》 了解更多。

八.多重class定义
一个标签可以同时定义多个class。例如:我们先定义两个样式,第一个样式背景为#666;第二个样式有10 px的边框。
.one{width:200px;background:#666;}
.two{border:10px solid #F00;}
在页面代码中,我们可以这样调用
<div class=one two></div>
这样最终的显示效果是这个div既有#666的背景,也有10px的边框。是的,这样做是可以的,你可以尝试一下。

九.使用子选择器(descendant selectors)
CSS初学者不知道使用子选择器是影响他们效率的原因之一。子选择器可以帮助你节约大量的class定义。我们来看下面这段代码:
<div id=subnav>
<ul>
<li class=subnavitem> <a href=# class=subnavitem>Item 1</a></li>>
<li class=subnavitemselected> <a href=# class=subnavitemselected> Item 1</a> </li>
<li class=subnavitem> <a href=# class=subnavitem> Item 1</a> </li>
</ul>
</div>
这段代码的CSS定义是:
div#subnav ul { /* Some styling */ }
div#subnav ul li.subnavitem { /* Some styling */ }
div#subnav ul li.subnavitem a.subnavitem { /* Some styling */ }
div#subnav ul li.subnavitemselected { /* Some styling */ }
div#subnav ul li.subnavitemselected a.subnavitemselected { /* Some styling */ }
你可以用下面的方法替代上面的代码
<ul id=subnav>
<li> <a href=#> Item 1</a> </li>
<li class=sel> <a href=#> Item 1</a> </li>
<li> <a href=#> Item 1</a> </li>
</ul>
样式定义是:
#subnav { /* Some styling */ }
#subnav li { /* Some styling */ }
#subnav a { /* Some styling */ }
#subnav .sel { /* Some styling */ }
#subnav .sel a { /* Some styling */ }
用子选择器可以使你的代码和CSS更加简洁、更加容易阅读。
 
十.不需要给背景图片路径加引号
为了节省字节,我建议不要给背景图片路径加引号,因为引号不是必须的。例如:
background:url(images/***.gif) #333;
可以写为
background:url(images/***.gif) #333;
如果你加了引号,反而会引起一些浏览器的错误。
 
十一.组选择器(Group selectors)
当一些元素类型、class或者id都有共同的一些属性,你就可以使用组选择器来避免多次的重复定义。这可以节省不少字节。
例如:定义所有标题的字体、颜色和margin,你可以这样写:
h1,h2,h3,h4,h5,h6 {
font-family:Lucida Grande,Lucida,Arial,Helvetica,sans-serif;
color:#333;
margin:1em 0;
}
如果在使用时,有个别元素需要定义独立样式,你可以再加上新的定义,可以覆盖老的定义,例如:
h1 { font-size:2em; }
h2 { font-size:1.6em; }
 
十二.用正确的顺序指定链接的样式
当你用CSS来定义链接的多个状态样式时,要注意它们书写的顺序,正确的顺序是::link :visited :hover :active。抽取第一个字母是LVHA,你可以记忆成LoVe HAte(喜欢讨厌)。为什么这么定义,可以参考Eric Meyer的《Link Specificity》。
如果你的用户需要用键盘来控制,需要知道当前链接的焦点,你还可以定义:focus属性。:focus属性的效果也取决与你书写的位置,如果你希望聚焦元素显示:hover效果,你就把:focus写在:hover前面;如果你希望聚焦效果替代:hover效果,你就把:focus放在:hover后面。
 
十三.清除浮动
一个非常常见的CSS问题,定位使用浮动的时候,下面的层被浮动的层所覆盖,或者层里嵌套的子层超出了外层的范围。
通常的解决办法是在浮动层后面添加一个额外元素,例如一个div或者一个br,并且定义它的样式为clear: both。这个办法有一点牵强,幸运的是还有一个好办法可以解决,参看这篇文章《How To Clear Floats Without Structural Markup》(注:本站将尽快翻译此文)。
上面2种方法可以很好解决浮动超出的问题,但是如果当你真的需要对层或者层里的对象进行clear的时候怎么办?一种简单的方法就是用overflow属性,这个方法最初的发表在《Simple Clearing of Floats》,又在《Clearance》和《Super simple clearing floats》中被广泛讨论。
上面那一种clear方法更适合你,要看具体的情况,这里不再展开论述。另外关于float的应用,一些优秀的文章已经说得很清楚,推荐你阅读:《Floatutorial》、《Containing Floats》和《Float Layouts》
 
十四.横向居中(centering)
这是一个简单的技巧,但是值得再说一遍,因为我看见太多的新手问题都是问这个:CSS如何横向居中?你需要定义元素的宽,并且定义横向的margin,如果你的布局包含在一个层(容器)中,就象这样:
<!-- 你的布局这里开始 -->
你可以这样定义使它横向居中:
#wrap {
width:760px; /* 修改为你的层的宽度 */
margin:0 auto;
}
但是IE5/Win不能正确显示这个定义,我们采用一个非常有用的技巧来解决:用text-align属性。就象这样:
body {
text-align:center;
}
#wrap {
width:760px; /* 修改为你的层的宽度 */
margin:0 auto;
text-align:left;
}
第一个body的text-align:center; 规则定义IE5/Win中body的所有元素居中(其他浏览器只是将文字居中) ,第二个text-align:left;是将#warp中的文字居左。
 
十五.导入(Import)和隐藏CSS
因为老版本浏览器不支持CSS,一个通常的做法是使用@import技巧来把CSS隐藏起来。例如:
@import url(main.css);
然而,这个方法对IE4不起作用,这让我很是头疼了一阵子。后来我用这样的写法:
@import main.css;
这样就可以在IE4中也隐藏CSS了,呵呵,还节省了5个字节呢。想了解@import语法的详细说明,可以看这里《centricle’s css filter chart》
 
十六.针对IE的优化
有些时候,你需要对IE浏览器的bug定义一些特别的规则,这里有太多的CSS技巧(hacks),我只使用其中的两种方法,不管微软在即将发布的IE7 beta版里是否更好的支持CSS,这两种方法都是最安全的。
* 1.注释的方法
o (a)在IE中隐藏一个CSS定义,你可以使用子选择器(child selector):
html>body p {
/* 定义内容 */
}
o (b)下面这个写法只有IE浏览器可以理解(对其他浏览器都隐藏)
* html p {
/* declarations */
}
o (c)还有些时候,你希望IE/Win有效而IE/Mac隐藏,你可以使用反斜线技巧:
/* */
* html p {
declarations
}
/* */
* 2.条件注释(conditional comments)的方法
另外一种方法,我认为比CSS Hacks更加经得起考验就是采用微软的私有属性条件注释(conditional comments)。用这个方法你可以给IE单独定义一些样式,而不影响主样式表的定义。就象这样:
<!--[if IE]>
<link rel=stylesheet type=text/css href=ie.css />
<![endif]-->
 
十七.调试技巧:层有多大?
当调试CSS发生错误,你就要象排版工人,逐行分析CSS代码。我通常在出问题的层上定义一个背景颜色,这样就能很明显看到层占据多大空间。有些人建议用 border,一般情况也是可以的,但问题是,有时候border 会增加元素的尺寸,border-top和boeder-bottom会破坏纵向margin的值,所以使用background更加安全些。
另外一个经常出问题的属性是outline。outline看起来象boeder,但不会影响元素的尺寸或者位置。只有少数浏览器支持outline属性,我所知道的只有Safari、OmniWeb、和Opera。
 
十八.CSS代码书写样式
在写CSS代码的时候,对于缩进、断行、空格,每个人有每个人的书写习惯。在经过不断实践后,我决定采用下面这样的书写样式:
selector1,
selector2 {
property:value;
}
当使用联合定义时,我通常将每个选择器单独写一行,这样方便在CSS文件中找到它们。在最后一个选择器和大括号{之间加一个空格,每个定义也单独写一行,分号直接在属性值后,不要加空格。
我习惯在每个属性值后面都加分号,虽然规则上允许最后一个属性值后面可以不写分号,但是如果你要加新样式时容易忘记补上分号而产生错误,所以还是都加比较好。
最后,关闭的大括号}单独写一行。
空格和换行有助与阅读。

longhorn server Key

 
2. Click Invitations
 
3. Input your E-mail address  and  Password for the Sign in
 
4. Input the Invitaion ID : TE06-KVM4-3RM9  to GO
 
5. Click Product Keys
 
6. Click Request New Product Key
 
 
Key :  49HMJ-F2KY4-K984X-62FFP-V9X84
 
this key only for Longhorn Server , not Windows Vista.
2006/12/6

Windows Server 2003 IIS6 PHP

 第一步:相关软件准备(以下软件全部是截止到2006年7月7日的)
PHP: 推荐PHP-4.4.0-Win32的ZIP解压版本
   4.4.0版本下载:http://cn.php.net/get/php-4.4.0-Win32.zip/from/a/mirror
   5.1.2版本下载:http://cn.php.net/get/php-5.1.2-Win32.zip/from/a/mirror
   5.1.4版本下载:http://download.discuz.net/env/php-5.1.4-Win32.zip
MySQL:配合PHP4推荐MySQL5.0.22的WIN系统安装版本
   5.0.22版本下载:http://download.discuz.net/env/mysql-essential-5.0.22-win32.msi
   官方下载地址:http://dev.mysql.com/downloads/mysql/5.0.html
ZendOptimizer:版本越新越好啊(目前最新是2.6.2)
   官方下载地址:https://www.zend.com/store/free_download.php?pid=13
   (虽然下载是免费的,但是要注册用户,才可以下载,为了方便大家的使用,公开我注册好的用户名:ideacmblog密码:chm.ideacm.cn,方便大家使用,希望大家在使用这个帐号的时候不要修改密码和用于其它非正当途径)
phpMyAdmin:这个当然也是越新越好啊
   官方下载地址:http://www.phpmyadmin.net/home_page/downloads.php
   国内下载地址:http://www.crsky.com/soft/4190.html
                               http://www.skycn.com/soft/10687.html
好了,软件下载好了,现在就开始安装了;
假设你的系统在C:\\,如果你的系统不是C:\\那么下面请自己对应修改。同时,为了避免C:\\因为重装系统等等各种原因,对C盘进行操作,和在系统盘下备份、转移也很不方便,所以不建议将PHP相关软件安装在C:\\,这里我把它安装在D:\\php目录下(这个目录你也可以自己设定,如果你要安装到不同墓立涉及到路径修改的请修改下面对应的路径即可)
第二步:安装PHP(我取PHP安装路径取为D:\\php\\php4\\(为避混淆,PHP5.1.x版本安装路径取为D:\\php\\php5\\)
   (1)、下载得到的 php-4.4.0-Win32.zip ,解压至D:\\php目录,将得到二级目录php-4.4.0-Win32,改名为 php4,也即得到PHP文件存放目录D:\\php\\php4\\[如果是PHP5.1.2,得到的文件是php-5.1.2-Win32.zip,直接全部接压至D:\\php\\php5目录即可得PHP文件存放目录D:\\php\\php5\\];
   (2)、再将D:\\php\\php4目录和D:\\php\\php4\\dlls目录[PHP5为D:\\php\\php5\\]下的所有dll文件拷到c:\\Windows\\system32(win2000系统为 c:/winnt/system32/)下,如果目录下有这些dll文件就覆盖已有的dll文件;
   (3)、将D:\\php\\php4\\php.ini-dist用记事本打开,利用记事本的查找功能(Ctrl+F)搜索并修改:
   register_globals = Off
   把 Off 改成 On ,即得到 register_globals = On
   注:这个对应PHP的全局变量功能,考虑有很多PHP程序需要全局变量功能故打开,打开后请注意-PHP程序的严谨性,如果不需要推荐不修改保持默认Off状态
再搜索
   extension_dir =
,并将其路径指到你的 PHP 目录下的 extensions 目录,比如:修改extension_dir = "./"为extension_dir = "D:/php/php4/extensions/" ;
PHP扩展功能目录[PHP5对应修改为extension_dir = "D:/php/php5/ext/"]
在D:\\php下建立文件夹并命名为tmp
查找
   ;upload_tmp_dir =
将;upload_tmp_dir该行的注释符,即前面的分号“;”去掉,使该行在php.ini文档中起作用。upload_tmp_dir是用来定义上传文件存放的临时路径,在这里你还可以修改并给其定义一个绝对路径,这里设置的目录必须有读写权限。
这里我设置为upload_tmp_dir = D:/php/tmp  (即前面建立的这个文件夹呵)
搜索找到
   ;Windows Extensions
将下面一些常用的项前面的;去掉
   ;extension=php_mbstring.dll
   ;extension=php_curl.dll
   ;extension=php_dbase.dll
   ;extension=php_gd2.dll
这个是用来支持GD库的,一般需要,必选
   ;extension=php_ldap.dll
   extension=php_zip.dll
去掉前面的";"
对于PHP5的版本还需要查找
   ;extension=php_mysql.dll
并同样去掉前面的";"
这个是用来支持MYSQL的,由于PHP5将MySQL作为一个独立的模块来加载运行的,故要支持MYSQL必选
查找
   ;session.save_path =
去掉前面;号,本文这里将其设置置为
session.save_path = D:/php/tmp
其他的你可以选择需要的去掉前面的;然后将该文件另存为为php.ini到C:\\Windows ( Windows 2000 下为 C:\\WINNT)目录下,注意更改文件后缀名为ini,得到C:\\Windows\\php.ini ( Windows 2000 下为 C:\\WINNT\\php.ini)
若路径等和本文相同可直接保存到C:\\Windows ( Windows 2000 下为 C:\\WINNT)目录下使用若路径等和本文相同可直接保存到C:\\Windows ( Windows 2000 下为 C:\\WINNT)目录下使用
一些朋友经常反映无法上传较大的文件或者运行某些程序经常超时,那么可以找到C:\\Windows ( Windows 2000 下为 C:\\WINNT)目录下的PHP.INI以下内容修改:
max_execution_time = 30     ; 这个是每个脚本运行的最长时间,可以自己修改加长,单位秒
max_input_time = 60        ; 这是每个脚本可以消耗的时间,单位也是秒
memory_limit = 8M      ; 这个是脚本运行最大消耗的内存,也可以自己加大
upload_max_filesize = 2M ; 上载文件的最大许可大小 ,自己改吧,一些图片论坛需要这个更大的值
第四步:配置IIS使其支持PHP
   IIS如何安装,那就不用说了吧!
   PHP 支持 CGI 和 ISAPI 两种安装模式,CGI 更消耗资源,容易因为超时而没有反映,但是实际上比较安全,负载能力强,节省资源,但是安全性略差于CGI,本人推荐使用 ISAPI 模式。故这里只解介绍 ISAPI 模式安装方法:
   在“控制面板”的“管理工具”中选择“Internet 服务管理器”,打开 IIS 后停止服务,对于Win2003系统展开”Internet 服务管理器“的下级树一般为你的”计算机名“选择”网站“并单击右键选择“属性”,在弹出的属性窗口上选择“ISAPI 筛选器”选项卡找到并点击“添加”按钮,在弹出的“筛选器属性”窗口中的“筛选器名称”栏中输入:PHP ,再将浏览可执行文件使路径指向 php4isapi.dll 所在路径,如本文中为:D:\\php\\php4\\sapi\\php4isapi.dll[PHP5对应路径为D:\\php\\php5\\php5isapi.dll]。
打开“站点属性”窗口的“主目录”选项卡,找到并点击“配置”按钮
在弹出的“应用程序配置”窗口中的”应用程序映射“选项卡找到并点击“添加”按钮新增一个扩展名映射,在弹出的窗口中单击“浏览”将可执行文件指向 php4isapi.dll 所在路径,如本文中为:D:\\php\\php4\\sapi\\php4isapi.dll[PHP5对应路径为D:\\php\\php5\\php5isapi.dll],扩展名为 .php ,动作限于”GET,HEAD,POST,TRACE“,将“脚本引擎”“确认文件是否存在”选中,然后一路确定即可。如果还想支持诸如 .php3 ,.phtml 等扩展名的 PHP 文件,可以重复“添加”步骤,对应扩展名设置为需要的即可如.PHPX。
此步操作将使你服务器IIS下的所有站点都支持你所添加的PHP扩展文件,当然如果你只需要部分站点支持PHP,只需要在“你需要支持PHP的Web站点”比如“默认Web站点”上单击右键选择“属性”,在打开的“ Web 站点属性”“主目录”选项卡,编辑或者添加PHP的扩展名映射即可或者将你步需要支持PHP的站点中的PHP扩展映射删除即可
再打开“站点属性”窗口的“文档”选项卡,找到并点击“添加”按钮,向默认的 Web 站点启动文档列表中添加 index.php 项。您可以将 index.php 升到最高优先级,这样,访问站点时就会首先自动寻找并打开 index.php 文档。
确定 Web 目录的应用程序设置和执行许可中选择为纯脚本,然后关闭 Internet 信息服务管理器
对于2003系统还需要在“Internet 服务管理器”左边的“WEB服务扩展”中设置ISAPI 扩展允许,Active Server Pages 允许
完成所有操作后,重新启动IIS服务。
在CMD命令提示符中执行如下命令:
net stop w3svc
net stop iisadmin
net start w3svc
到此,PHP的基本安装已经完成,我们已经使网站支持PHP脚本。
检查方法是,在 IIS 根目录下新建一个文本文件存为 php.php ,内容如下:
phpinfo();
?>
打开浏览器,输入:http://localhost/php.php,将显示当前服务器所支持 PHP 的全部信息,可以看到 Server API的模式为:ISAPI 。
或者利用PHP探针检测,到http://depoch.net/download.htm下载后解压到你的站点根目录下并访问即可
第三步:安装MySQL
   对于MySQL4.0.26下载得到的是mysql-4.0.26-win32.zip,解压到mysql-4.0.26-win32目录双击执行 Setup.exe 一路Next下一步,选择安装目录为D:\\php\\MySQL和安装方式为Custom自定义安装,再一路Next下一步即可。
   安装完毕后,在CMD命令行中输入并运行:
   D:\\php\\MySQL\\bin\\mysqld-nt -install
   如果返回Service successfully installed.则说明系统服务成功安装
新建一文本文件存为MY.INI,编辑配置MY.INI,这里给出一个参考的配置
  
[mysqld]
basedir=D:/php/MySQL
#MySQL所在目录
datadir=D:/php/MySQL/data
#MySQL数据库所在目录,可以更改为其他你存放数据库的目录
#language=D:/php/MySQL/share/your language directory
#port=3306
set-variable    = max_connections=800
skip-locking
set-variable        = key_buffer=512M
set-variable        = max_allowed_packet=4M
set-variable        = table_cache=1024
set-variable        = sort_buffer=2M
set-variable        = thread_cache=64
set-variable        = join_buffer_size=32M
set-variable        = record_buffer=32M
set-variable        = thread_concurrency=8
set-variable        = myisam_sort_buffer_size=64M
set-variable        = connect_timeout=10
set-variable        = wait_timeout=10
server-id        = 1
[isamchk]
set-variable        = key_buffer=128M
set-variable        = sort_buffer=128M
set-variable        = read_buffer=2M
set-variable        = write_buffer=2M
[myisamchk]
set-variable        = key_buffer=128M
set-variable        = sort_buffer=128M
set-variable        = read_buffer=2M
set-variable        = write_buffer=2M
[WinMySQLadmin]
Server=D:/php/MySQL/bin/mysqld-nt.exe
保存后复制此MY.INI文件到C:\\Windows ( Windows 2000 下为 C:\\WINNT)目录下
回到CMD命令行中输入并运行:
net start mysql
MySQL 服务正在启动 .
MySQL 服务已经启动成功。
将启动 MySQL 服务;
DOS下修改ROOT密码:当然后面安装PHPMYADMIN后修改密码也可以通过PHPMYADMIN修改
格式:mysqladmin -u用户名 -p旧密码 password 新密码
例:给root加个密码ideacmblog
首先在进入CMD命令行,转到MYSQL目录下的bin目录,然后键入以下命令
mysqladmin -uroot password ideacmblog
注:因为开始时root没有密码,所以-p旧密码一项就可以省略了。
D:\\php\\MySQL\\bin>mysqladmin -uroot password ideacmblog回车后ROOT密码就设置为ideacmblog了
如果你下载的是 MySQL5.x或者MySQL4.1.x,例mysql-5.0.18-win32:解压后双击执行 Setup.exe ,Next下一步后选择Custom自定义安装,再Next下一步选择安装路径这里我们选择D:\\php\\MySQL,继续Next下一步跳过Sign UP完成安装。
安装完成后会提示你是不是立即进行配置,选择是即可进行配置。当然一般安装后菜单里面也有配置向导MySQL Server Instance Config Wizar,运行后按下面步骤配置并设置ROOT密码即可
Next下一步后选择Standard Configuration
Next下一步,钩选Include .. PATH
Next下一步,设置ROOT密码,建议社设置复杂点,确保服务器安全!
Apply完成后将在D:\\php\\MySQL目录下生成MY.INI配置文件,添加并启动MySQL服务

第四步:安装 Zend Optimizer
   下载后得到 ZendOptimizer-2.6.2-Windows-i386.exe ,直接双击安装即可,安装过程要你选择 Web Server 时,选择 IIS ,然后提示你是否 Restart Web Server,选择是,完成安装之前提示是否备份 php.ini ,点确定后安装完成。我这里安装到D:\\php\\Zend
以下两步的目录根据你自己的默认WEB站点目录来选,当然也可以选择到D:\\php\\Zend目录
   Zend Optimizer 的安装向导会自动根据你的选择来修改 php.ini 帮助你启动这个引擎。下面简单介绍一下 Zend Optimizer 的配置选项。以下为本人安装完成后 php.ini 里的默认配置代码(分号后面的内容为注释):
zend_extension_ts="D:\\php\\Zend\\lib\\ZendExtensionManager.dll"
;Zend Optimizer 模块在硬盘上的安装路径。
zend_extension_manager.optimizer_ts="D:\\php\\Zend\\lib\\Optimizer-2.6.2"
;优化器所在目录,默认无须修改。
zend_optimizer.optimization_level=1023
;优化程度,这里定义启动多少个优化过程,默认值是 15 ,表示同时开启 10 个优化过程中的 1-4 ,我们可以将这个值改为 1023 ,表示开启全部10个优化过程。
调用phpinfo()函数后显示:
Zend Engine v1.3.0, Copyright (c) 1998-2004 Zend Technologies with Zend Extension Manager v1.0.9, Copyright (c) 2003-2006, by Zend Technologies with Zend Optimizer v2.6.2, Copyright (c) 1998-2006, by Zend Technologies 则表示安装成功。
第五步:安装GD库
   这一步在前面PHP.INI配置中去掉“;extension=php_gd2.dll”前面的;实际上已经安装好了~
[在php.ini里找到"extension=php_gd2.dll"这一行,并且去掉前面的分号,gd库安装完成,用echophpinfo();测试是否成功! ]
第六步:安装phpMyAdmin
   下载得到 phpMyAdmin-2.8.2.zip ,将其解压到D:\\php\\或者 IIS 根目录,改名phpMyAdmin-2.8.2为phpMyAdmin,并在IIS中建立新站点或者虚拟目录指向该目录以便通过WEB地址访问,这里建立默认站点的phpMyAdmin虚拟目录指向D:\\php\\phpMyAdmin目录通过http://localhost/phpmyadmin/访问
找到并打开D:\\php\\phpMyAdmin\\libraries(phpMyAdmin2.7.0和以前的版本在D:\\php\\phpMyAdmin\\目录下)目录下的 config.default.php ,做以下修改:
查找
$cfg[\'PmaAbsoluteUri\']
设置你的phpmyadmin的WEB访问URL,如本文中:$cfg[\'PmaAbsoluteUri\'] = \'http://localhost/phpmyadmin/\'; 注意这里假设phpmyadmin在默认站点的根目录下
搜索
$cfg[\'blowfish_secret\'] =
设置COOKIES加密密匙,如ideacmblog则设置为$cfg[\'blowfish_secret\'] = \'ideacmblog\';
搜索$cfg[\'Servers\'][$i][\'auth_type\'],默认为config,是不安全的,不推荐,推荐使用cookie,将其设置为$cfg[\'Servers\'][$i][\'auth_type\']     = \'cookie\';
注意这里如果设置为config请在下面设置用户名和密码!例如:
$cfg[\'Servers\'][$i][\'user\']          = \'root\';      // MySQL user-----MySQL连接用户
$cfg[\'Servers\'][$i][\'password\']      = \'ideacmblog\';  
搜索$cfg[\'DefaultLang\'] ,将其设置为 zh-gb2312 ;
搜索$cfg[\'DefaultCharset\'] ,将其设置为 gb2312 ;
打开浏览器,输入:http://localhost/phpMyAdmin/ ,若 IIS 和 MySQL 均已启动,输入用户ROOT密码ideacmblog(如没有设置密码则密码留空)即可进入phpMyAdmin数据库管理。
在进http://localhost/phpmyadmin/输入用户名和密码后,如果出现 Client does not support authentication protocol requested by server; consider upgrading MySQL client 错误提示,
这是由于MySQL 4.1 及其后版本验证协议使用的密码哈希算法与老的客户端不兼容,因此需要在MySQL Command Line Client里面用命令同步兼容密码:
进入MySQL Command Line Client后MYSQL的提示符是:mysql>
然后执行:
SET PASSWORD FOR \'root\'@\'localhost\' = OLD_PASSWORD(\'你的ROOT管理密码\');
再可以进入phpmyadmin管理,每新建一个用户的时候都要这样执行命令一次,注意把root替换成你新建的用户名和对应的密码。
首先点击权限进入用户管理,删除除ROOT和主机不为localhost的用户并重新读取用户权限表,这里同样可以修改和设置ROOT的密码,添加其他用户等。
phpMyAdmin 的具体功能,请慢慢熟悉,这里就不赘述。
至此所有安装完毕。
第七步:目录结构以及NTFS格式下安全的目录权限设置:
   当前目录结构为
                                            D:\\php
                                                 |
                +—————+——————+———————+———————+
            php4(php5)    tmp             MySQL                     Zend         phpMyAdmin
   D:\\php设置为管理员和SYSTEM完全权限即可,其他用户均无权限
   对于其下的二级目录
   php4(或者php5)、 tmp 给EVERYONE完全权限
   MySQL 、Zend 管理员和SYSTEM完全权限
   phpMyAdminWEB匿名用户读取运行权限
posted @ 2007-08-14 08:37  网络金领  阅读(2679)  评论(0编辑  收藏  举报