在ASP.NET中使用Session常见问题集锦
C#(C Sharp发音为“C霎普”)牢固地植根于C和C++语言族谱中,并且会很快被C和C++程序员所熟悉。
C#的目标在于把Visual Basic的高生产力和C++本身的能力结合起来。
C#作为Microsoft Visual Studio 7.0的一部分提供给用户。
除了C#以外,Visual Studio还支持Visual Basic、Visual C++和描述语言VBScript和Jscript。
所有这些语言都提供对Microsoft .NET平台的访问能力,它包括一个通用的执行引擎和一个丰富的类库。
Microsoft .NET平台定义了一个“通用语言子集”(CLS),是一种混合语言,它可以增强CLS兼容语言和类库间的无缝协同工作能力。
对于C#开发者,这意味着既是C#是一种新的语言,它已经可以对用老牌工具如Visual Basic和Visual C++使用的丰富类库进行完全访问。C#自己并没有包含一个类库。
本章的其余部分描述这种语言的基本特性。
规范的“Hello,World”程序可以按照下面例子编写:
using System;
class Hello
{
static void Main() {
Console.WriteLine("Hello, world");
}
}
C#程序的源代通常存储在一个或多个扩展名为.cs的文件中,例如hello.cs。如果使用Visual Studio提供的命令行编译器,这样的程序可以用命令行命令来编译
csc hello.cs
这样就会生成一个名为hello.exe的可执行程序。程序的输出如下:
Hello, world
下面对这个程序进行详细的研究:
· 使用System;指令涉及到一个名称空间(namespace)叫作System,这是在Microsoft .NET类库中提供的。这个名称空间包括在Mian方法中使用的Console类。名称空间提供了一种用来组织一个类库的分层方法。使用“using”命令后,就可以无障碍地使用名称空间中的各种类型成员。“Hello,world”程序中使用的Console.WriteLine是System.Console.WriteLine的简写。
· Main方法是类Hello中的一个成员,它有static的说明符,所以它是类Hello中的一个方法而不是此类中的实例。
· 对于一个应用程序的主入口点-称开始执行的方法-通常是一个称为Main的静态方法。
· “Hello,world”的输出是通过使用类库产生的。语言本身并没有提供类库。作为替代,它使用一个通用类库,这个类库也可以被诸如Visual Basic和Visual C++的语言所使用。
对于C和C++开发者来说,会有兴趣知道对一些没有出现在“Hello,world”程序的东西。
· 程序没有把Main设为全局方法。在全局级别上不支持方法和变量;这些元素通常包含在类型声明当中(例如,类或结构的声明)。
· 程序中不使用“::”或“->”操作符。“::”不再是一个操作符,而“->”操作符也只是在程序的某个小片断中才会使用。操作符“.”用于符合名称,例如Console.WriteLine。
· 程序中不包括前向声明。因为声明的顺序不重要,所以不再需要前向声明。
· 程序中不使用#include关键字。程序中的从属关系是象征性的而不是字面上地。这个系统消除了在用不同语言编写的程序间的障碍。例如,Console类可以用另外一种语言编写。
原文:http://blog.csdn.net/cuike519/archive/2005/09/27/490316.aspx
问:为什么Session在有些机器上偶尔会丢失?
答:可能和机器的环境有关系,比如:防火墙或者杀毒软件等,尝试关闭防火墙。
问:为什么当调用Session.Abandon时并没有激发Session_End方法?
答:首先Session_End方法只支持InProc(进程内的)类型的Session。其次要激发Session_End方法,必须存在Session(即系统中已经使用Session了),并且至少要完成一次请求(在这次请求中会调用该方法)。
问:为什么当我在InProc模式下使用Session会经常丢失?
答:该问题通常是由于应用程序被回收导致的,因为当使用进程内Session时,Session是保存在aspnet_wp进程中,当该进程被回收Session自然也就没有了,确定该进程是否被回收可以通过查看系统的事件查看器获得信息。
具体信息请参考:
Session variables are lost intermittently in ASP.NET applicationshttp://support.microsoft.com/default.aspx?scid=kb;en-us;Q316148
在1.0的时候也有一个bug会导致工作进程被回收并重启,该bug已经在1.1和sp2中修复。
关于该bug的详细信息请参考:
ASP.NET Worker Process (Aspnet_wp.exe) Is Recycled Unexpectedly. http://support.microsoft.com/default.aspx?scid=kb;en-us;Q321792
问:为什么当Session超时或者Abandoned后,新Session的ID和原来的相同?
答:因为SessionID是保存在客户端浏览器的实例里,当Session超时在服务器重新建立Session时,将使用浏览器传来的SessionID,所以当Session超时后,再重新建立后SessionID并不变。
问:为什么每次请求的SessionID都不相同?
答:该问题可能是没有在Session里面保存任何信息引起的,即程序中任何地方都没有使用Session。当Session中保存信息之后SessionID将一直和浏览器相关,此时的SessionID将不会在变化。
问:ASP和ASP.NET之间是否可以共享Session?
答:可以。但是这是一个比较复杂的过程,微软提供了官方的解决方案,请参考:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ConvertToASPNET.asp
问:什么类型的对象可以保存在Session里?
答:这依赖使用的Session的模式,当使用的是进程内(InProc)的Session那么可以轻松的保存任何对象。如果你使用了非InProc的模式,则只能保存可以序列化和反序列化的对象,如果此时保存的对象不支持序列化,则不能保存到这种模式(非InProc)的Session里。
问:为什么在Session_End中不能使用Response.Redirect和Server.Transfer方法跳转页面?
答:Session_End是一个在服务器内部激发的事件处理函数。它是基于一个服务器内部的计时器的,在激发该事件时服务器上并没有相关的HttpRequest对象,因此此时并不能使用Response.Redirect和Server.Transfer方法。
问:在Session_End中是否可以获得HttpContext对象?
答:不行,因为这个事件并没有和任何的请求(Request)相关联,没有基于请求的上下文。
问:在Web Service中该如何使用Session?
答:为了在Web Service中使用Session,需要在Web Service的调用方做一些额外的工作,必须保存和存储调用Web Service时使用的Cookie。详细信息请参考MSDN文档的HttpWebClientProtocol.CookieContainer属性。然而,如果你使用代理服务器访问Web Service由于框架的限制,两者不能共享Session。
问:在自定义自己的HttpHandler的时候,为什么不能使用Session?
答:在实现自己的HttpHandler的时候,如果希望使用Session必须实现下面的两个标记接口中的一个:IRequiresSessionState和IReadOnlySessionState,这些接口没有任何方法需要实现,只是一个标记接口和使用INamingContainer接口的方法一样。
问:当我使用webfarm时,当我重定向到其他的Web服务器时Session为什么会丢失?
答:详细信息请参考:
PRB: Session State Is Lost in Web Farm If You Use SqlServer or StateServer Session Modehttp://support.microsoft.com/default.aspx?scid=kb;en-us;325056
问:为什么我的Session在Application_OnAcquireRequestState方法中无效?
答:Session只有在HttpApplication.AcquireRequestState事件调用以后才会有效。
详细信息请参考:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconhandlingpublicevents.asp
问:如果使用了cookieless,我该如何从HTTP页面定向到HTTPS?
答:请尝试下面的方法:
String originalUrl = "/fxtest3/sub/foo2.aspx";
String modifiedUrl = "https://localhost" + Response.ApplyAppPathModifier(originalUrl);
Response.Redirect(modifiedUrl);
问:Session在global.asax中的那些事件中有效?
答:Session只有在AcquireRequestState事件之后有效,该事件之后的事件都可以使用Session。
问:如何获得当前Session中保存的所有对象?
答:可以通过遍历所有的Session.Keys来获得。代码如下:
ArrayList sessionCollection = new ArrayList();
foreach (string strKey in Session.Keys){
sessionCollection.Add(Session[strKey]);
}
问:是否可以在不同的应用程序中共享Session?
答:不能直接共享。可以参考如何在ASP和ASP.NET之间共享Session。
问:Session.Abandon和Session.Clear有何不同?
答:主要的不同之处在于当使用Session.Abandon时,会调用Session_End方法(InProc模式下)。当下一个请求到来时将激发Session_Start方法。而Session.Clear只是清除Session中的所有数据并不会中止该Session,因此也不会调用那些方法。
问:为了可以顺序访问Session的状态值,Session是否提供了锁定机制?
答:Session实现了Reader/Writer的锁机制:
当页面对Session具有可写功能(即页面有<%@ Page EnableSessionState="True" %>标记),此时直到请求完成该页面的Session持有一个写锁定。
当页面对Session具有只读功能(即页面有<%@ Page EnableSessionState="ReadOnly" %>标记),此时知道请求完成该页面的Session持有一个读锁定。
读锁定将阻塞一个写锁定;读锁定不会阻塞读锁定;写锁定将阻塞所有的读写锁定。这就是为什么两个框架中的同一个页面都去写同一个Session时,其中一个要等待另一个(稍快的那个)完成后,才开始写。
问:Session平滑超时意味着什么?
答:Session平滑超时意味着只要你的页面访问(使用)了Session,超时时间将被刷新(可以理解为重新计时),即从该页面请求开始,将重新计算超时时间。但是,该页面不能禁用Session。它会自动的访问当前页面的Session,刷新超时时间。
问:在global.asax中的事件处理函数中Session为什么无效?
答:依赖于在哪个事件处理函数中使用Session,Session在AcquireRequestState事件之后才有效,该事件之后的所有事件处理函数都可以使用Session,之前的则不能。
问:当我写一个依赖于当前应用的Session的组件时,为什么不能直接使用Session["Key"]获得其值?
答:Session["Key"]实际上是this.Session["Key"],它是作为Page的一个属性提供的,所以在你的组件中不能直接使用这个属性。你可以通过下面的方式使用Session:
HttpContext.Current.Session["Key"] = "My Seesion Value";
问:当我使用InProc模式保存Session时,此时的Session是保存在哪里?
答:不同的IIS的处理方式不同,
当使用的是IIS5的时候Session是保存在aspnet_wp.exe的进程空间里的。
当使用的是IIS6时,默认情况下所有的应用程序共享应用程序池,Session保存在w3wp.exe的进程空间中。
问:Session的超时设置是分钟还是秒?
答:是分钟,默认为20分钟。
问:当页面出现错误后我的Session是否将被保存?我需要在Session_End中处理一些清理工作,但是失败了,为什么?
答:Session_End只有在Session运行在InProc模式下才会被执行。Session_End使用的帐号是运行aspnet_wp工作进程的帐号(这个可以在machine.config中设置)。因此,如果在Session_End方法里,使用集成安全性链接到SQL,它将使用aspnet_wp进程的帐号打开链接,此时成功与否则依赖于你的SQL的安全性设置。
问:为什么当我设置cookieless为true是我在重定向的时候会丢失Session?
答:当使用cookieless时,你必须使用相对路径替换程序中的绝对路径,如果使用绝对路径ASP.NET将无法在URL中保存SessionID。
例如:将myDirmySubdirdefault.aspx换成..default.aspx即可。
问:如何将SortedList存储到Session或者Cache里?
答:请参考下面的方法:
SortedList x = new SortedList();
x.Add("Key1", "ValueA");
x.Add("Key2", "ValueB");
保存到Session中:
Session["SortedList1"] = x;
使用下面方法获得之:
SortedList y = (SortedList) Session["SortedList1"];
Chahe则同理。
问:我为什么会获得这样的错误信息“Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive”?
答:这个问题可能在一个已经安装了Microsoft Visual Studio .NET开发环境的机器上,再安装Window Sharepoint Server(WSS)后出现。
WSS ISAPI过滤器会处理所有的请求。当你通过虚拟目录浏览一个ASP.NET的应用程序时,ISAPI过滤器不会给文件夹目录分配URL。
解决方法是:不要再安装了WSS的机器上使用Session。
详细信息请参考:
Session state cannot be used in ASP.NET with Windows SharePoint Serviceshttp://support.microsoft.com/default.aspx?scid=kb;en-us;837376
问:如何删除Session变量?
答:想要删除Session变量可以使用HttpSessionState.Remove()方法。
问:是否有办法知道应用程序的Session在运行时占用了多少内存?
答:没有。目前这个值时无法考证的,至少我现在还没有看到这方面的资料。但是可以通过性能监视器以及程序代码大概估算出来一个值。
问:当页面中是否了frameset,发现在每个frame中显示页面的SessionID在第一次请求时都不相同,为什么?
答:原因是你的frameset是放在一个htm页面上而不是ASPX页面。
在一般情况下,如果frameset是aspx页面,当你请求页面时,它首先将请求发送到Web服务器,此时已经获得了SessionID,接着浏览器会分别请求Frame中的其他页面,这样所有页面的SessionID就是一样的,就是FrameSet页面的SessionID。
然而如果你使用Html页面做FrameSet页面,第一个请求将是HTML页面,当该页面从服务器上返回是并没有任何Session产生,接着浏览器会请求Frame里面的页面,这样这些页面都会产生自己的SessionID,所以在这种情况下就会出现这种问题。当你重新刷新页面时,SessionID就会一样,并且是最后一个请求页面的SessionID。
问:是否可以将不同应用程序的Session保存在相同的SQL Server服务器的不同数据库上。
答:可以,请参考:
FIX: Using one SQL database for all applications for SQL Server session state may cause a bottleneckhttp://support.microsoft.com/default.aspx?scid=kb;en-us;836680
问:在Session_End是我是否可以获得有效的HttpSessionState和HttpContext对象?
答:你可以在这个方法中获得HttpSessionState对象,可以直接使用Session来访问即可。但是不能获得HttpContext对象,因为该事件并没有和任何请求相关联,因此不存在上下文对象。
问:在SQLServer模式下使用Session,为什么我的Session不过期?
答:在SqlServer模式下,Session的过期是通过SQL Agent的注册工作完成的,请检查你的SQL Agent是否运行?
问:当我设置EnableSessionState为“ReadOnly”后,但是我在InProc模式下依然可以修改Session的值,这是为什么?
答:即使EnableSessionState标示为ReadOnly,但是在InProc模式下用户依然可以编辑Session。唯一不同的是,在请求过程中Session将不会被锁住。
问:我如何才能避免在链接SQL时指定密码?
答:使用信任链接或者使用加密的链接串。有关这方面的详细信息请参考:
How To Use the ASP.NET Utility to Encrypt Credentials and Session State Connection Strings http://support.microsoft.com/default.aspx?scid=kb;en-us;329290
问:我在我自己的类中该如何使用Session呢?
答:可以使用HttpContext.Current.Session方式使用,具体方法如下:
HttpContext.Current.Session["SessionKey"] = "SessionValue";
类似的你还可以使用这种方式使用Application对象。
问:为什么在切换成SQLServer模式后我的请求被挂起了?
答:检查在Session里面是否都保存的是可以保存在SQLServer模式下的对象,即这些对象必须支持序列化。
问:当Session设置成cookieless后会有什么影响?
答:当把cookieless设置成true时,主要会有下面的约束:
1、在页面中不能使用绝对链接
2、在应用程序中在除了Http和Https之间的切换时需要完成一些其他的步骤。
如果发送一个链接给其他人,此时的URL里面将包含Session ID的信息,所以两个人将公用一个Session。
问:是否可以将Session保存在数据库中?
答:当然可以,详细信息请参考:http://support.microsoft.com/default.aspx?scid=kb;en-us;311209
运行环境:
IBM T30
CPU:1.8GHZ
内存:256M
硬盘:40G
OS:Windows Server 2000 SP4
Visual Studio .NET 2003(Framework v1.1.4322)
Microsoft SQL Server 2000
机器配置跑不动 VS2005,很是郁闷,故本次旅行仅限制在Framework v1.1.4322。
废话少说,第一个例子,使用记事本编写C#语句输出XML文件。
第一步:打开记事本,输入以下代码。
// 文件test001.cs
using System;
using System.Xml;
public class Hello51CTO {
public static void Main(string [ ] args) {
XmlTextWriter writer = new XmlTextWriter(Console.Out);
writer.WriteStartDocument( );
writer.WriteElementString("网址", "http://c.blog.51cto.com/");
writer.WriteEndDocument( );
writer.Close( );
}
}
// 文件test001.cs结束
第二步:打开一个DOS窗口(运行,CMD,回车),我们使用如下命令行编译test001.cs
C:WINNTMicrosoft.NETFrameworkv1.1.4322csc /debug /target:exe test001.cs
// csc是C#的编译器,生成一个同名的exe文件test001.exe
// 参数/debug 是让编译器生成一个包含调试信息的附加文件test001.pdb
第三步:如果编译成功,则会生成两个文件test001.exe和test001.pdb,我们在DOS窗口下输入test001,运行刚刚生成的文件,可以看到输出如下内容:
<?xml version="1.0" encoding="gb2312"?><网址>http://c.blog.51cto.com/</网址>
怎么样,我们用记事本输出了一个简单的XML文件。
例如,对TextBox txt,可以:
txt.Attributes.Add("onclick", "fcn0();");
那么,在web页面上click它的时候,就会调用fcn0这个javascript函数。
1.1、例外的情况是,对于IDE无法辨认的属性的解析。
比如对一个RadioButton rbt,IDE不能辨认onclick这个属性,那么,类似上面的语句,
rbt.Attributes.Add("onclick", "fcn1(this);");
在.net framework 1.1中,将解析成
<input type=radio id=rbt onclick="fcn1(this);">...
而在在.net framework 1.0中,将解析成
<span onclick="fcn1(this);"><input type=radio id=rbt>...</span>
注意到,fcn1中,参数this对应的对象就不同了。这是一个细微的差别。
2、而对于HTML control,需要多做一点事情。
在设计aspx页面的时候,从工具栏拖一个web form control,比如说,TextBox到页面,会发生两件事:
一、aspx页面多一句
<asp:TextBox id="TextBox1" style="..." runat="server" Width="102px" Height="25px"></asp:TextBox>
二、code behind多一句
protected System.Web.UI.WebControls.TextBox TextBox1;
如果是html control,那么,第一句中,runat="server"不会出现,而第二局不会被自动添加。
因此,如果要访问html control,需要
一、aspx页面的语句中添加runat="server"属性,成为
<INPUT style="..." type="text" size="9" id="htxt" runat="server">
二、code behind中显示的声明
protected System.Web.UI.HtmlControls.HtmlInputText htxt;
注意到第一句的id和第二句的变量名是相同的。
2.1、注意到,前面System.Web.UI.WebControls.TextBox对应的html control是System.Web.UI.HtmlControls.HtmlInputText,对应的html的tag是<INPUT type="text">,
相应的,html的tag <body>对应的html control是
public System.Web.UI.HtmlControls.HtmlGenericControl myBody;
2.2、有一点例外的是html的<form> tag对应的onsubmit的事件。看这样一个aspx页面
<%@ Page language="c#" Codebehind="WebForm2.aspx.cs" AutoEventWireup="false" Inherits="TestCs.WebForm2" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm2</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
<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">
function fcn1()
{
prompt("hi", "fcn1");
}
</script>
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="WebForm2" method="post" runat="server" onsubmit="fcn1();">
<asp:Button id="Button1" style="Z-INDEX: 103; LEFT: 423px; POSITION: absolute; TOP: 83px" runat="server" Width="86px" Height="29px" Text="Button"></asp:Button>
<asp:DropDownList id="DropDownList1" style="Z-INDEX: 104; LEFT: 284px; POSITION: absolute; TOP: 163px" runat="server" Width="188px" Height="17px" AutoPostBack="True">
<asp:ListItem Value="a">a</asp:ListItem>
<asp:ListItem Value="b">b</asp:ListItem>
<asp:ListItem Value="c">c</asp:ListItem>
</asp:DropDownList>
</form>
</body>
</HTML>
内容很简单,定义了一个javascript函数fcn1,放了一个Button Button1和一个autopostback的Dropdownlist DropDownList1,运行它,可以看到:点击Button1,会先执行fcn1然后postback,而选择DropDownList1的不同选项,将只会postback,而不会触发fcn1。
微软autopostback=true的webcontrol实现postback,原理是这样的:
一、如果此aspx页面有autopostback=true的webcontrol,那么会写下面一段javascript语句定义一个叫__doPostBack的javascript函数。
<script language="javascript">
<!--
function __doPostBack(eventTarget, eventArgument) {
var theform;
if (window.navigator.appName.toLowerCase().indexOf("netscape") > -1) {
theform = document.forms["WebForm2"];
}
else {
theform = document.WebForm2;
}
theform.__EVENTTARGET.value = eventTarget.split("$").join(":");
theform.__EVENTARGUMENT.value = eventArgument;
theform.submit();
}
// -->
</script>
二、例如是上面的dropdownlist,将会render成:
<select name="DropDownList1" onchange="__doPostBack('DropDownList1','')" language="javascript" id="DropDownList1" style="...">
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
</select>
这样,通过javscript调用theform.submit();来submit form,postback,但是,theform.submit将不会触发form的onsubmit事件!
这是微软的一个bug。
解决的方法可以看这里:http://www.devhawk.net/art_submitfirefixup.ashx,这里提供了一个dll及源代码,使用的时候,在project的reference里加入这个dll,然后在web.config中加上一段
<httpModules>
<add type="DevHawk.Web.SubmitFireFixupModule,SubmitFireFixupModule" name="SubmitFireFixupModule" />
</httpModules>
就可以了。
3、一个应用。
常常听到抱怨,说如果在Browser端用javascript改动了某个<select>元素,那么,它对应的Server端的DropDownList不能得知这个更新。
这种情况可能出现在“级联”的DropDownList中,比如第一个DropDownList是省份,第二个是城市;也可能出现在,从第一个DropDownList选择某些项加入到第二个DropDownList中。
对此使用以上的技术,我做了一个这样的解决方案(类似于ViewState的方法):
一、我定义了一个长宽都是0的TextBox txtWrap,并把所有我想处理的DropDownList都加上AthosOsw="True" 这样的属性,准备处理。
二、参照上面2.2的内容,我加入了SubmitFireFixupModule,来保证触发form的onsubmit事件。
三、form的onsubmit事件将执行javascript函数fcnAthosOnSubmitWrap,它将遍历AthosOsw属性为True的DropDownList,记下数据,最后合并起来放到txtWrap里,其实这就是一个序列化的过程。代码如下:
function fcnAthosOnSubmitWrap()
{
txtWrap = document.all["txtWrap"];
var i;
var strWrap = '';
for(i=0;i<document.all.length;i++)
{
ctrl = document.all[i];
if(ctrl.tagName.toUpperCase() == 'SELECT' && typeof(ctrl.AthosOsw) != 'undefined' )
{
if(ctrl.AthosOsw.toUpperCase() == 'TRUE')
{
strWrap += fcnAthosWrapSelect(ctrl) + '&&&';
}
}
}
if(strWrap.length>3)
txtWrap.value = strWrap.substring(0, strWrap.length-3);
};
//AthosOsw
function fcnAthosWrapSelect(ctrlSelect)
{
var i;
var strWrapSelect = ctrlSelect.id + '&' + ctrlSelect.tagName;
var strValue='';
var strText='';
for(i=0; i<ctrlSelect.options.length; i++)
{
strValue = ctrlSelect.options[i].value;
strText = ctrlSelect.options[i].text;
strWrapSelect += '&&' + i + '&' + strValue.replace(/&/g, '%26') + '&' + strText.replace(/&/g, '%26');
};
return strWrapSelect;
};
四、form的Page_Load中调用clsCommon.UnwrapControl(this, txtWrap.Text);来反序列化。clsCommon是我的工具类,UnwrapControl方法代码如下:
static public void UnwrapControl(System.Web.UI.Page pgUnwrap, String strUnwrap)
{
Regex r3 = new Regex("(&&&)"); // Split on hyphens.
Regex r2 = new Regex("(&&)"); // Split on hyphens.
Regex r1 = new Regex("(&)"); // Split on hyphens.
String[] sa3, sa2, sa1;
String s3, s2, s1;
int i3, i2, i1;
String strId, strTagName;
System.Web.UI.Control ctrlUnwrap;
DropDownList ddlUnwrap;
ListItem liAdd;
s3 = strUnwrap;
sa3 = r3.Split(s3);
for(i3=0;i3<(sa3.Length+1)/2;i3++)
{
s2 = sa3[i3*2];
if(s2.Length>0)
{
sa2 = r2.Split(s2);
if(sa2.Length>1)
{
s1 = sa2[0];
sa1 = r1.Split(s1);
if(sa1.Length==3)
{
strId = sa1[0];
strTagName = sa1[2];
ctrlUnwrap = pgUnwrap.FindControl(strId);
if(ctrlUnwrap !=null)
{
if(strTagName == "SELECT")
{
ddlUnwrap = (DropDownList)ctrlUnwrap;
ddlUnwrap.Items.Clear();
for(i2=1; i2 < (sa2.Length+1)/2;i2++)
{
s1 = sa2[i2*2];
sa1 = r1.Split(s1);
liAdd = new System.Web.UI.WebControls.ListItem(sa1[4],sa1[2]);
ddlUnwrap.Items.Add(liAdd);
}
}
}
}
}
}
}
}
请点击下载种子
http://c.blog.51cto.com/get/325/vs2005.rar
cs_vs_2005_pro_dvd.iso.torrent
Visual Studio 2005 Professional Edition - DVD - (Simplified Chinese)
cs_vs_2005_vsts_trial_dvd.iso.torrent
Visual Studio 2005 Team Suite Trial Edition - DVD - (For Evaluation Only) (Simplified Chinese)
cs_vwd_2005_express.iso.torrent
Visual Web Developer 2005 Express Edition (Simplified Chinese)
cs_msdn_vs_2005_dvd.iso.torrent
MSDN Library for Visual Studio 2005 - DVD (Simplified Chinese)
cs_visio_enterprise_architects_2005.iso.torrent
Visio for Enterprise Architects (Visual Studio 2005) (Simplified Chinese)
en_sql_2005_ent_x86_dvd.iso.torrent
SQL Server 2005 Enterprise Edition - 32-bit - DVD (English)
注:VS2005是180day试用版,但添加注册码升级到正式版,然后点升级就OK了!
SN:KYTYH-TQKW6-VWPBQ-DKC8F-HWC4J
我经常听到有人问这个问题:“在ASP.NET Web应用程序中我应该用DataReader类还是DataSet类呢?”在很多文章以及新闻组的贴子中我经常看到这样的误解,即认为DataReader(SqlDataReader或OleDbDataReader的缩写)比DataSet好。有时候我也会看到相反的说法。事实上,Microsoft创建了这两个数据存取类是因为它们都是我们所需要的。每个类都有其优点和不足,你可以根据应用环境来选择用哪一个。
本文就两者的选择问题做了很清楚的讲述,可以让你在运用ASP.NET时,在选择DataReader类或DataSet类的方面得到一些指南。在基于客户端的Windows Form应用程序环境下,这些规则可能会改变。我在做这些讲述时,假设你已经用过DataReader和DataSet类了,并对它们很熟悉。
运用DataReader类
下面就是运用DataReader类的理想条件: 你读取的数据必须是新的,所以在每次需要数据的时候,你都必须从数据库读取。创建一个DataReader类不会消耗很多内存,不过随着负荷的增加,DataSet上的性能也会很快地提高(参考资源中Visual Studio Magazine中的文章)。
你对每行数据的需求很简单。该情况的最好的例子就是简单地将DataReader绑定到一个Web控件,如DataGrid或DropDownList。
你只需要从数据库中以只向前的(forward-only) 、只读的形式来存取XML数据。在这种情况下,你可以用SQLCommand对象的ExcecuteXmlReader()方法来得到一个XmlReader类(相当于XML版的DataReader)。这就需要一个运用FOR XML子句的SQL Server查询,或者一个包含有效XML的ntext字段。
你计划对数据库进行几个重复的调用,来读取一小块信息。在这种情况下,我们前面提到过的性能数据会有更大的提高。
的确,使DataSet类更强大的许多功能只适用于基于客户端的Windows Form应用程序,比如在多个表之间建立关系的功能。在很多情况下,DataSet类都比DataReader类更有优势,而且在有些情况下,你根本就不能用DataReader类。
运用DataSet类
在下面的情况,你应该考虑运用DataSet类: 你构建了一个Web service,它运用的数据是你作为返回值读取的数据。因为DataReader类必须保持到数据库的连接,所以它们不能被序列化到XML中,也不能被发送给一个Web service的调用者。
你需要排序或筛选数据。在运用一个DataView对象(呈现为DataTable类的DefaultView属性,它包含一个DataSet类)来排序或筛选数据前,我们先试着用SQL查询(如WHERE和ORDER BY语句)来实现这些功能,并运用更轻量级、更快的DataReader类。然而,有时侯用这种方法是不行的,或者当你需要多次地对数据进行排序或筛选时就不能用DataReader。
针对同一请求,你需要多次遍历数据。你只能在DataReader中循环一次。如果你想将多个ServerControl类绑定到同一个数据集,那么选择DataSet就更好。DataReader类不能被绑定到多个ServerControl类,因为它是只向前读取的。在这种情况下,如果要使用DataReader,必须从数据库读取两次数据。
你需要存储数据,而后续的页面请求可能会用到的这些数据。如果数据只被请求它的专门的人使用,你可以将DataSet类保存在一个Session变量中。如果数据可以被任何人访问,那么你可以将它保存在一个Application变量中,或保存在Cache中(我建议使用后一种方法,因为它支持时间期限和回调(callback))。因为DataReader类必须一直打开对数据库的连接,而且它一次只能保存一行数据,所以它们不能在跨页面请求中被保存。
你需要对一个结果集的每个元素实现特殊的、耗时的功能。例如,如果你从一个数据库读取一列邮政编码,并想通过调用一个Web service来得到每个地区的详细的天气状况信息,那么选择DataSet就会更好。这是因为,当你在用DataReader类时,在关闭DataReader类前,与数据库的连接不会被释放回连接池。在数千页面请求之间潜在的一个很小的延时都会造成Web应用程序的很高的访问量,从而就会消耗完可用的连接。相反,DataSet可以在前端读取所有的数据,并可以马上关闭与数据库的连接,将它返回到连接池,因此其它的页面请求就可以用这个连接了。
你需要在一个两维范例中加载并处理XML数据。DataSet类对于XML很有用,因为你可以将DataView用于XML,对根本的数据进行排序和筛选,就同处理一个数据库结果集一样。然而,需要注意的是在System.Xml名字空间中有很多类,你可以将它们用于更复杂的XML操作。
你的数据源不是一个数据库。虽然OleDbDataReader可以用于任何OLEDB数据提供者(可能指向一个数据库,也可能不指向一个数据库),但DataSet对象可以从一个XML文件直接加载数据,并动态地解释它的schema。DataSet类也可以将XML数据写回一个数据流或一个文件。
从上面的讲述我们就可以看到,DataSet类比DataReader类有更多的功能,这就可以让你在更多的情况下运用它们。但这并不意味着你总是在用DataSet类。你需要在ASP.NET中完成的相当大一部分的任务都属于DataReader的范畴。
尽管如此,毫无疑问,从重要程度或复杂程度的角度来说,DataSet类在很多ASP.NET Web应用程序中都起着很重要的作用。你可以通过明智的缓存来最小化数据库往返,从而降低DataSet类的“性能损害”。DataReader和DataSet都是一个成功的ASP.NET Web应用程序的重要的部件。重要的是,我们需要了解何时、在哪里可以最好的使用它们。
WMI 是 Windows Management Instrumentation 。
主要功能是:
访问本地主机的一些信息和服务,可以管理远程计算机,比如:获取磁盘信息,获取磁盘大小,获取网卡地址,获取CPU信息,获取硬盘型号,共享目录,重启,关机,创建进程,关闭进程等。(前提是你拥有足够的权限)呵呵,很强大吧。
使用方法:
很简单,在项目中引用 System.Management.dll 即可。
下面给出部分代码:
private void Page_Load(object sender, System.EventArgs e)
{
TextBox1.Text += getdisk();
TextBox1.Text += getmacaddress();
TextBox1.Text += cpuinfo();
TextBox1.Text += hardinfo();
TextBox1.Text += baseboard();
}
/// <summary>
/// 获取磁盘信息
/// </summary>
/// <returns></returns>
public string getdisk()
{
// disk["DriveType"] 的返回值意义如下:
// 1 No type
// 2 Floppy disk
// 3 Hard disk
// 4 Removable drive or network drive
// 5 CD-ROM
// 6 RAM disk
string a="";
SelectQuery query=new SelectQuery("Select * From Win32_LogicalDisk");
ManagementObjectSearcher searcher=new ManagementObjectSearcher(query);
foreach(ManagementBaseObject disk in searcher.Get())
{
a += (" "+disk["Name"] +" "+disk["DriveType"] + " " + disk["VolumeName"]) + diskinfo(disk["Name"].ToString()) +"n";
}
return a;
}
/// <summary>
/// 获取磁盘大小
/// </summary>
/// <param name="d"></param>
/// <returns></returns>
public string diskinfo(string d)
{
string a="";
ManagementObject disk = new ManagementObject("win32_logicaldisk.deviceid='"+d+"'");
disk.Get();
a = (" " + disk["Size"] + " bytes");
return a;
}
/// <summary>
/// 获取网卡地址
/// </summary>
/// <returns></returns>
public string getmacaddress()
{
string a="";
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
foreach(ManagementObject mo in moc)
{
if((bool)mo["IPEnabled"] == true)
a = "网卡:" + mo["MacAddress"].ToString() + "n";
mo.Dispose();
}
return a;
}
/// <summary>
/// 获取CPU信息
/// </summary>
/// <returns></returns>
public string cpuinfo()
{
string a="";
ManagementClass mcobject = new ManagementClass("Win32_Processor");
ManagementObjectCollection moc = mcobject.GetInstances();
foreach(ManagementObject mo in moc)
{
a += "CPU:" + mo.Properties["ProcessorId"].Value.ToString() + "n";
}
return a;
}
/// <summary>
/// 获取硬盘型号
/// </summary>
/// <returns></returns>
public string hardinfo()
{
string a="";
ManagementClass mcobject = new ManagementClass("Win32_DiskDrive");
ManagementObjectCollection moc = mcobject.GetInstances();
foreach(ManagementObject mo in moc)
{
a += "硬盘型号:" + mo.Properties["Model"].Value.ToString() + mo.Properties[""].Value.ToString() + "n";
}
return a;
}
public string baseboard()
{
string a="";
SelectQuery query=new SelectQuery("SELECT * FROM Win32_BaseBoard");
ManagementObjectSearcher searcher=new ManagementObjectSearcher(query);
foreach(ManagementBaseObject disk in searcher.Get())
{
a += "主板制造商: "+disk["Manufacturer"] +"n型号: "+disk["Product"] + "n序列号: " + disk["SerialNumber"] +baseinfo() +"n";
}
return a;
}
public string baseinfo()
{
string a="";
SelectQuery query=new SelectQuery("Select SerialNumber From Win32_BIOS");
ManagementObjectSearcher searcher=new ManagementObjectSearcher(query);
foreach(ManagementBaseObject disk in searcher.Get())
{
a = disk["SerialNumber"].ToString();
}
return a;
}
参考资料
msdn WMI SDK:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/wmi_reference.asp