ant 的个人资料microant照片日志列表更多 工具 帮助

日志


8月25日

gridview存储过程分页(二)

在服务器端主要是初始化gridview,也就是第一页。然后就是页码按钮的处理事件,代码如下:
protected void Page_Load(object sender, EventArgs e)
    
{
        
if (!IsPostBack)
        
{
            BindGV(
this.gvTest, "A101"5,11"CID""CID"null);

            
this.lbtnPrev.Enabled = false;
            
this.lblCurrentInfo.Text = "1";
            
this.lblCount.Text =  getPageNum("A101"5).ToString() ;
        }

    }


    
public int getPageNum(string tableName, int pagesize)
    
{
        
using (SqlDataObject sodo = new SqlDataObject())
        
{
            
string strSql = "select count(*) from " + tableName;
            
int count =Convert.ToInt32(sodo.ExecuteScalar(strSql));

            
int pagenum =Convert.ToInt32(Math.Ceiling(Convert.ToDouble(count/pagesize)));

            
return pagenum;
        }

    }


    
/**//// <summary>
    
/// 按钮处理事件
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>

    public void PageIndex_Changed(object sender, EventArgs e)
    
{
        LinkButton linkbtn 
= (LinkButton)sender;
        
switch (linkbtn.ID.Trim())
        
{
            
case "lbtnFirst":
                BindGV(
this.gvTest, "A101"511"CID""CID"null);

                
this.lblCurrentInfo.Text = "1";

                
break;
            
case "lbtnPrev":

                BindGV(
this.gvTest, "A101"5, Convert.ToInt32(this.lblCurrentInfo.Text) - 11"CID""CID"null);

                
this.lblCurrentInfo.Text = (Convert.ToInt32(this.lblCurrentInfo.Text) - 1).ToString();


                
break;
            
case "lbtnNext":

                BindGV(
this.gvTest, "A101"5, Convert.ToInt32(this.lblCurrentInfo.Text) + 11"CID""CID"null);

                
this.lblCurrentInfo.Text = (Convert.ToInt32(this.lblCurrentInfo.Text) + 1).ToString();



                
break;
            
case "lbtnLast":
                BindGV(
this.gvTest, "A101"5, Convert.ToInt32(this.lblCount.Text), 1"CID""CID"null);

                
this.lblCurrentInfo.Text = this.lblCount.Text;

                
break;
        }

        
if (Convert.ToInt32(this.lblCurrentInfo.Text) >= Convert.ToInt32(this.lblCount.Text) && Convert.ToInt32(this.lblCurrentInfo.Text) <=1)
        
{
            
this.lbtnPrev.Enabled = false;
            
this.lbtnNext.Enabled = false;
            
this.lbtnFirst.Enabled = false;
            
this.lbtnLast.Enabled = false;
        }

        
else if (Convert.ToInt32(this.lblCurrentInfo.Text) >= Convert.ToInt32(this.lblCount.Text))
        
{
            
this.lbtnPrev.Enabled = true;
            
this.lbtnNext.Enabled = false;
            
this.lbtnFirst.Enabled = true;
            
this.lbtnLast.Enabled = false;
        }

        
else if (Convert.ToInt32(this.lblCurrentInfo.Text) <= 1)
        
{
            
this.lbtnPrev.Enabled = false;
            
this.lbtnNext.Enabled = true;
            
this.lbtnFirst.Enabled = false;
            
this.lbtnLast.Enabled = true;
        }

        
else
        
{
            
this.lbtnPrev.Enabled = true;
            
this.lbtnNext.Enabled = true;
            
this.lbtnFirst.Enabled = true;
            
this.lbtnLast.Enabled = true;
        }

                
        
    }


    
/**//// <summary>
    
/// 绑定到gridview
    
/// </summary>
    
/// <param name="gv">gridview</param>
    
/// <param name="tableName">分页的表名</param>
    
/// <param name="size">页码大小</param>
    
/// <param name="pageindex">第几页</param>
    
/// <param name="isAsc">升降序</param>
    
/// <param name="OderColumName">排序的列</param>
    
/// <param name="KeyID">主键</param>
    
/// <param name="condictions">查询条件</param>

    private void BindGV(GridView gv, string tableName, int size, int pageindex, int isAsc, string OderColumName,string KeyID, string condictions)
    
{
        
using (SqlDataObject sodo = new SqlDataObject())
        
{
            SqlParameter[] sps 
= new SqlParameter[7];
            sps[
0= new SqlParameter("@TableName", tableName);
            sps[
1= new SqlParameter("@PageSize", size);
            sps[
2= new SqlParameter("@PageIndex", pageindex);
            sps[
3= new SqlParameter("@IsAsc"1);
            sps[
4= new SqlParameter("@OderColumName", OderColumName);
            sps[
5= new SqlParameter("@KeyID", KeyID);
            sps[
6= new SqlParameter("@Conditions", condictions);
 
   
           DataTable dt = sodo.getDataTable("sp""sp_CTE", sps);
            gv.DataSource 
= dt.DefaultView;
            gv.DataBind();
        }

    }
 

gridview存储过程分页(一)

     抽空写一下自己用的关于GridView存储过程分页的代码,优点就不用多说了,主要是用于数据库端分页,解决数据量过大的分页问题。存储过程还是以前写的CTE方法的分页,还是在这里贴一下代码吧,具体请见存储过程分页实现代码,2005 T-SQL新增功能一文。
USE [WGSMSDbase]
GO
/**//****** 对象:  StoredProcedure [dbo].[sp_CTE]    脚本日期: 08/25/2007 11:39:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO


-- =============================================
--
 Author:        <Author,,microant>
--
 Create date: <Create Date,,20070705>
--
 Description:    <Description,,CTE分页>
--
 =============================================
CREATE PROCEDURE [dbo].[sp_CTE]
    
-- Add the parameters for the stored procedure here
    @TableName nvarchar(200= 'testTable',    --表名
    @PageSize int = 15,        --页面大小
    @PageIndex int =2    ,    --页面的序号
    --@IsCountNull bit =1,    --返回记录是否为空
    @IsAsc bit = 1    ,    --是否卫升序,升序为1,降序为0
    @OderColumName nvarchar(200= null,        --排序字段名
    @KeyID nvarchar(50= 'id',        --主键
    @Conditions nvarchar(500= null --查询条件
)
AS

    
-- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    
declare @strSql nvarchar(1000)
    
declare @tempstr nvarchar(1000)
    
declare @orderstr nvarchar(400)
    
declare @ctestr nvarchar(400)
    
    
--判断排序方式,@IsAsc =1 升序, 0降序,设置排序语句
    if @IsAsc = 1
    
begin
        
if(@OderColumName is null or @OderColumName = '')
            
set @orderstr = ' order by ' + @KeyID + ' asc'
        
else
            
set @orderstr = ' order by ' + @OderColumName + ' asc'
    
end
    
else
    
begin
        
if(@OderColumName is null or @OderColumName = '')
            
set @orderstr = ' order by ' + @KeyID + ' desc'
        
else
            
set @orderstr = ' order by ' + @OderColumName + ' desc'
    
end
    
    
--CTE
    set @ctestr ='with Table_CET
    as
    (
        select 
            CEILING((ROW_NUMBER() OVER (
' + @orderstr + '))/' + str(@PageSize+ ') as page_num, * 
        from 
' + @TableName +
    
')' ;
    
begin
    
if(@Conditions is null or @Conditions = '')
        
set @strSql = @ctestr + 'select * from Table_CET where page_num = ' + str(@PageIndex);
    
else
        
set @strSql = @ctestr + 'select * from Table_CET where page_num = ' + str(@PageIndex)+ ' and ' + @Conditions;
    
print @strSql
end    
    
begin
        
exec sp_executesql  @strSql
    
end



客户端代码如下,主要包含首页,末页,上一页,下一页,当前页码,总页码等一些必要信息,最主要的就是给按钮添加处理事件OnClick。
8月23日

关于updatepanel中注册执行javascript

    好些天都在糊里糊涂,最近也比较懒,居然看到了个留言,永远不更新的博客一等奖,相当尴尬,哈哈。写一些最近自己或别人遇到的小问题吧。
    1、关于updatepanel注册js
      最近在项目里需要用到altas,本人也是新手,老用最简单的updatepanel,在注册脚本时也遇到了困难,无法注册。本来是在updatepanel中放了一个gridview,偶想在girdview中一个模板列点击弹出一个窗体,注册 window.open()来解决问题。本来不是在updatepanel中,所以用 ClientScript.RegisterStartupScript直接注册挺好使。
      在拖入updatepanel后发现无法注册脚本,想想RegisterStartupScript本来是在页面加载时启动js的,在updatepanel中部分刷新,肯定是无法注册的。
    后来发现了ScriptManager.RegisterStartupScript方法,挺好使,呵呵。
     ScriptManager.RegisterClientScriptBlock(UpdatePanelName, typeof(UpdatePanel), "标识key", "脚本", true);
    下面是一个demo,模板列定义如下:


protected void gvClientInfo_RowCommand(object sender, GridViewCommandEventArgs e)
    {
& nbsp;       
//如果是linkButton被点击
        if(e.CommandName.Equals("linkbtnCID"))
        {
            LinkButton lbtn 
= (LinkButton)e.CommandSource;
            GridViewRow dgRow 
= (GridViewRow)lbtn.Parent.Parent;
            
string tmpText = lbtn.Text.ToString();          
            tmpText 
="window.open('customerDetailsInfo.aspx?CID=" + tmpText + "' ,'newwindow','height=550,
                width=700, menubar=no ')
";
            ScriptManager.RegisterStartupScript(
this.UpdatePanel2, this.GetType(), "click", tmpText, true);      
      
        }
    }


    2、关于RegisterStartupScript,RegisterClientScriptBlock 

      RegisterStartupScript 将 js嵌入到页面的底部,</form> 的前面< br />         RegisterClientScriptBlock 将 js嵌入到页面中开启元素 <form> 后面

    3、关于“该行已经属于另一个表”错误
       这个问是出现在不同dataTable之间的行复制出现的问题。
       看这个代码:

 DataTable tmpdt = sodo.getDataTable("text", strSql, sp);             
 dt.Rows.Add(tmpdt.Rows[
0]);
     
       这个明显的错误就是tmpdt的行是一个对象引用,相当于一个指针,错误是难免的,可有以下解决办法:< br />
DataTable tmpdt = sodo.getDataTable("text", strSql, sp);             
1、 dt.Rows.Add(tmpdt.Rows[
0].ItemArray);
2、 dt.ImportRow(tmpdt.Rows[0]);

2月6日

dll文件访问被拒绝

这个问题是在用 win2003 后碰到的,在2003系统下,用vs.net 开发 运行项目的时候经常碰到
"组件 访问被拒绝 --“/”应用程序中的服务器错.."
以前重新启动 IIS , 注销系统都没有,一定要重新启动电脑,一直没找到答案,今天总算解决了
解决方法:
解决方法一:

1.开始 -- 管理工具 -- 计算机管理(Win2003的位置,其他操作系统类似)打开计算机管理
--展开计算机管理左边树中“服务和应用程序”节点,再在其下展开“索引服务”节点,停止服务,最好最快的方法

解决方法二:

2.1、开始 -- 管理工具 -- 计算机管理(Win2003的位置,其他操作系统类似)打开计算机管理
2.2、展开计算机管理左边树中“服务和应用程序”节点,再在其下展开“索引服务”节点,再在其下展开“System”节点,再在其下展开“目录”节点。
2.3、在计算机管理的右边我们可以看到配置的索引服务目录。
2.4、在“目录”节点上右击鼠标,选择“新建”--“目录”
2.5、在“添加目录”对话框中,路经输入框中输入 ASP.net 的临时文件目录。默认应该是:
c:\<WINDIR>\Microsoft.NET\Framework\<Version Number>\Temporary ASP.NET Files  目录。
<Version Number> 指你要处理的.net版本。
2.6、在“包含在索引中吗?”选项中,选择“否”
2.7、单击“确定”按钮
2.8、在“索引服务”节点上右键单击,重起索引服务即可。

解决方法三:
   1. 可以删除 bin\XX.pdb

1月4日

SQL Server不能启动的故障-[发生错误 1069 由于登陆失败而无法启动服务(转)

 

--是否修改了操作系统密码?

--修改操作系统密码,导致SQL不能启动的解决办法:

1.我的电脑--控制面板--管理工具--服务--右键MSSQLSERVER--属性--登陆--登陆身份--选择"本地系统帐户"

或:

2.我的电脑--控制面板--管理工具--服务--右键MSSQLSERVER--属性--登陆--登陆身份--选择"此帐户"--密码和确认密码中输入你修改后的administrator密码.

两者的区别:

选择第一种方式,以后修改了administrator密码,不用再调整(但要求登陆操作系统的是系统管理员)

选择第二种方式,以后修改了administrator密码,还要再重复做上面的操作.

第一个错误"SQL Server 不存在或访问被拒绝"通常是最复杂的,错误发生的原因比较多,需要检查的方面也比较多。一般说来,有以下几种可能性:

  1、SQL Server名称或IP地址拼写有误;

  2、服务器端网络配置有误;

  3、客户端网络配置有误。

  要解决这个问题,我们一般要遵循以下的步骤来一步步找出导致错误的原因。

  首先,检查网络物理连接:

   ping <服务器IP地址>    或者

   ping <服务器名称>

  如果 ping <服务器IP地址> 失败,说明物理连接有问题,这时候要检查硬件设备,如网卡、HUB、路由器等。还有一种可能是由于客户端和服务器之间安装有防火墙软件造成的,比如 ISA Server。防火墙软件可能会屏蔽对 ping、telnet 等的响应,因此在检查连接问题的时候,我们要先把防火墙软件暂时关闭,或者打开所有被封闭的端口。

  如果ping <服务器IP地址> 成功而 ping <服务器名称> 失败,则说明名字解析有问题,这时候要检查 DNS 服务是否正常。有时候客户端和服务器不在同一个局域网里面,这时候很可能无法直接使用服务器名称来标识该服务器,这时候我们可以使用HOSTS文件来进行名字解析,具体的方法是:

  1、使用记事本打开HOSTS文件(一般情况下位于C:\WINNT\system32\drivers\etc).

  2、添加一条IP地址与服务器名称的对应记录,如:

    172.168.10.24 myserver

  也可以在 SQL Server 的客户端网络实用工具里面进行配置,后面会有详细说明。

  其次,使用 telnet 命令检查SQL Server服务器工作状态:

   telnet <服务器IP地址> 1433

  如果命令执行成功,可以看到屏幕一闪之后光标在左上角不停闪动,这说明 SQL Server 服务器工作正常,并且正在监听1433端口的 TCP/IP 连接;如果命令返回"无法打开连接"的错误信息,则说明服务器端没有启动 SQL Server 服务,也可能服务器端没启用 TCP/IP 协议,或者服务器端没有在 SQL Server 默认的端口1433上监听。

  接着,我们要到服务器上检查服务器端的网络配置,检查是否启用了命名管道,是否启用了 TCP/IP 协议等等。我们可以利用 SQL Server 自带的服务器网络使用工具来进行检查。

  点击:程序 -> Microsoft SQL Server -> 服务器网络使用工具,打开该工具后看到的画面如下图所示:

  从这里我们可以看到服务器启用了哪些协议。一般而言,我们启用命名管道以及 TCP/IP 协议。

  点中 TCP/IP 协议,选择"属性",我们可以来检查 SQK Server 服务默认端口的设置,如下图所示:

  一般而言,我们使用 SQL Server 默认的1433端口。如果选中"隐藏服务器",则意味着客户端无法通过枚举服务器来看到这台服务器,起到了保护的作用,但不影响连接。

  检查完了服务器端的网络配置,接下来我们要到客户端检查客户端的网络配置。我们同样可以利用 SQL Server 自带的客户端网络使用工具来进行检查,所不同的是这次是在客户端来运行这个工具。

  点击:程序 -> Microsoft SQL Server -> 客户端网络使用工具, 打开该工具后看到的画面如下图所示:

  从这里我们可以看到客户端启用了哪些协议。一般而言,我们同样需要启用命名管道以及 TCP/IP 协议。

  点击 TCP/IP 协议,选择"属性",可以检查客户端默认连接端口的设置,如下图所示。

  该端口必须与服务器一致。

  单击"别名"选项卡,还可以为服务器配置别名。服务器的别名是用来连接的名称,连接参数中的服务器是真正的服务器名称,两者可以相同或不同。如下图中,我们可以使用myserver来代替真正的服务器名称sql2kcn-02,并且使用网络库 Named Pipes。别名的设置与使用HOSTS文件有相似之处。

  通过以上几个方面的检查,错误 1 发生的原因基本上可以被排除。下面我们再详细描述如何来解决错误 2。

  当用户尝试在查询分析器里面使用sa来连接SQL Server,或者在企业管理器里面使用sa来新建一个SQL Server注册时,经常会遇到如图 2 所示的错误信息。该错误产生的原因是由于SQL Server使用了"仅 Windows"的身份验证方式,因此用户无法使用SQL Server的登录帐户(如 sa )进行连接。解决方法如下所示:

  1、 在服务器端使用企业管理器,并且选择"使用 Windows 身份验证"连接上 SQL Server;

  2、 展开"SQL Server组",鼠标右键点击SQL Server服务器的名称,选择"属性",再选择"安全性"选项卡;

  3、 在"身份验证"下,选择"SQL Server和 Windows "。

  4、 重新启动SQL Server服务。

  在以上解决方法中,如果在第 1 步中使用"使用 Windows 身份验证"连接 SQL Server 失败,那么我们将遇到一个两难的境地:首先,服务器只允许了 Windows 的身份验证;其次,即使使用了 Windows 身份验证仍然无法连接上服务器。这种情形被形象地称之为"自己把自己锁在了门外",因为无论用何种方式,用户均无法使用进行连接。实际上,我们可以通过修改一个注册表键值来将身份验证方式改为 SQL Server 和 Windows 混合验证,步骤如下所示:

  1、点击"开始"-"运行",输入regedit,回车进入注册表编辑器;

  2、依次展开注册表项,浏览到以下注册表键:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\MSSQLServer]

  3、在屏幕右方找到名称"LoginMode",双击编辑双字节值;

  4、将原值从1改为2,点击"确定";

  5、关闭注册表编辑器;

  6、重新启动SQL Server服务。

  此时,用户可以成功地使用sa在企业管理器中新建SQL Server注册,但是仍然无法使用Windows身份验证模式来连接SQL Server。这是因为在 SQL Server 中有两个缺省的登录帐户:BUILTIN\Administrators 以及 <机器名>\Administrator 被删除。要恢复这两个帐户,可以使用以下的方法:

  1、打开企业管理器,展开服务器组,然后展开服务器;

  2、展开"安全性",右击"登录",然后单击"新建登录";

  3、在"名称"框中,输入 BUILTIN\Administrators;

  4、在"服务器角色"选项卡中,选择"System Administrators" ;

  5、点击"确定"退出;

  6、使用同样方法添加 <机器名>\Administrator 登录。

  以下注册表键

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\MSSQLServer\LoginMode

  的值决定了SQL Server将采取何种身份验证模式。该值为1,表示使用Windows 身份验证模式;该值为2,表示使用混合模式(Windows 身份验证和 SQL Server 身份验证)。

  看完如何解决前两个错误的方法之后,让我们来看一下如图 3 所示的第三个错误。

  如果遇到第三个错误,一般而言表示客户端已经找到了这台服务器,并且可以进行连接,不过是由于连接的时间大于允许的时间而导致出错。这种情况一般会发生在当用户在Internet上运行企业管理器来注册另外一台同样在Internet上的服务器,并且是慢速连接时,有可能会导致以上的超时错误。有些情况下,由于局域网的网络问题,也会导致这样的错误。

  要解决这样的错误,可以修改客户端的连接超时设置。默认情况下,通过企业管理器注册另外一台SQL Server的超时设置是 4 秒,而查询分析器是 15 秒(这也是为什么在企业管理器里发生错误的可能性比较大的原因)。具体步骤为:

  1、在企业管理器中,选择菜单上的"工具",再选择"选项";

  2、在弹出的"SQL Server企业管理器属性"窗口中,点击"高级"选项卡;

  3、在"连接设置"下的"登录超时(秒)"右边的框中输入一个比较大的数字,如 20。

  查询分析器中也可以在同样位置进行设置。

在windows控制面版-->管理工具-->服务-->MSSQLSERVER-->属性-->改为你的新的操作系统密码!或在windows控制面版-->管理工具-->服务-->MSSQLSERVER-->属性-->改为本地登陆!

10月22日

atlas

http://ajax.asp.net/docs/Overview/installing/default.aspx
10月10日

关于这个小任务的心得体会(一)

今天终于可以放松下来回顾一下关于做这么一个功能比较简单的blog主页的总结。以前一直都没有什么精力和心情进下来想一下,归纳一下。现在能停一停,看看自己走过的脚印,找找不足,整点经验,也好为以后不犯这种错误做点贡献。
言归正传,先说一下背景,老师给我们分配一小任务,要求给导师们做一主页,提供一个交流平台。
1、一定分析好需求。
其实,在一听这个要求时,我们脑中立马浮现的是blog,做一个blog网站。结果是二话没说,我们用了大名鼎鼎的.Text,大家都知道,现在很多国内大的blog网站都在用,比如oblog,博客园就是用的这一框架。
搭好平台之后,大家都知道.text功能强大,但是界面是典型的简约型,没经过界面调整促使需求的改变。
需求变了,最重要的是强调的界面,功能变得简单,只是提供一个文章发布,课件下载,还有博客应该有的一个基本的功能,RSS,搜索引擎等就不做要求。这样看来,.text就用不大上了。
但是再次对.text致敬,看了它的代码很受打击,也很是佩服。感觉那才是真正的面向对象,感觉用户控件用得很不错,以后要多加学习。
    现在的初步想法就是用用户控件把首页界面进行一次彻底重写,增加代码的重用性。现在出现的一个很大的毛病就是牵一发而动全身,首页的各个页面有一些重的部分没有进行一个很好的处理,只是实现了“代码级复用”(说的有点太自嘲了)
9月9日

ASP遗留的二十大积习(受打击了)

在技术更新的进程中, 仍然有一些人死抱着已经过了气的东西不放. 也有一些人虽然进入到新的世界, 但仍摆脱不了陈旧的习惯. 我没有用”陋习”这个词, 因为我对这个词也非常反感.
新技术应该有新技术的做法, 进入ASP.NET的世界, 就应该把以往的习惯改正, 全新的进入新的世界, 把ASP的破烂扔掉.
以下列举的都是错误的做法, 请不要误以为是推荐的做法而进行推广:

1. 使用server side include给ASPX引入共同的页面构图.
在ASP.NET的机制下, 应使用ASCX(web user control)来实现. ASCX提供了更多可控制接口. 并且更重要的是, ASCX是一个类. 一个实实在在的类. 可以全面控制它.

2.不使用web.config
web.config提供了非常丰富的配置管理接口. 是一个应用程序最核心的部分. 但是很多人的web.config往往是空的. 或者就从来没有修改过.

3.使用Response.Write向前端输出消息
ASP.NET平台下的Response和ASP的Response有很大的不同. 虽然表示同一含义, 但用法上已经大不相同. Response.Write的内容只会输出到页的最前端. 向前端输出消息的正确方法是使用PlaceHolder.

4.使用一系列session管理用户连接状态
这种方法在ASP里被滥用. 在ASP.NET环境下, 正确的做法应该是设计一个类. 结构化地保存数据. 将对session或者cookie的访问封装起来.

5.使用session验证身份
这几乎是通病. ASP.NET提供了一组用于用户身份验证的API. 类型是forms验证或者windows验证. 这一点quick start有一节讲解得很清楚. 可以绝大部分人还是依靠给session赋值来保持用户身份验证状态.

6.使用Response.Redirect重定向页
这一点在必要的时候可以使用. 但不可滥用. 事实证明滥用重定向将导致逻辑上的严重混乱. 这是在以页为程序单元的时候的做法. 使用front controller模式将使用户的操作逻辑集中起来]

7.使用太多ASPX页
ASP环境下的程序单元只有*.asp页, ASP.NET可不是这样, 还有后端的类库, ASCX等等. 应将业务逻辑分别集中在不同的单元, 而不应该一项操作使用一个ASPX. 更多时候ASPX将做为ASCX或者custom control的容器而管理页内逻辑. ASPX重用ASCX的同时, ASPX也做为统一的页构图重用.

8.在多个逻辑单元之间复制代码并修改相应逻辑
重用. 重用. 重用. 处理此类问题的原则是不出现任何相同或相似的过程. 如果你用上面的方法, 一旦出现重大逻辑更改, 带来的结果将是灾难性的.

9.害怕使用DataSet.
很多人被DataSet吓坏了. 认为”肯定”影响性能. 但连最初的尝试都不敢. 他们总认为他们的产品一定重大, 设计上应该”慎重”. 他们往往使用ArrayList或者设计低级的类来保存集合数据. 进行艰难的数据倒入工作.

10.对“性能”过多注意.
对ASP.NET ViewState的机制特别不满. 或者总是挖空心思迫害人家. 反倒把自己弄得很累. 如果在对付ViewState的同时多注意少连几次数据库也许更文明些.

11.应用程序根目录很乱.
ASP.NET是开发项目. 不是网站. 应该把不同的资源分类放置. 例如把所有静态资源(样式表, 脚本, 图像)组织到一起. 甚至可以写一组API来管理他们. ASPX应该放在一起. ASCX应该放在一起. .*.cs呢? 应该把他们放到另外一个project里.

12.不厌其烦的写访问数据库的过程
应该把这工作交给DataAccess Application Block. 你自己还要开关connection, 何苦呢.

13.自己写的东西最靠得住.
事实往往正好相反. 多注意使用人家写好的产品. 又不收你钱, 何苦那么爱面子呢.

14. 胡乱命名ASPX文件名
这是最让人痛苦的了. ASPX文件名不仅需要容易识别. 还应该遵循一定规则. 因为behind每个ASPX都会有一个同名的类, 想象一下, 多难受. 另外大部分人不知道管理自己的项目的name space. 让人好像看到一本帐一样.

15.从来不作继承或派生
一些具有相同行为的类, 应该从公共的基类派生出来. 实际意义上, 我们的ASPX应该有一个基类PageBase. 因为总有一些公共的特性需要抽象出来.

16.零property
他们的类(ASPX所对应)里只有private method. 不公开自己的任何秘密. 可以这一定是JAVA的遗老干的事.

17. 零ASCX
不用说, 他还没学会ASP.NET

18.使用DreamWeaver“画“ASPX
这批人是美工. 甚至有一些人在非常陶醉地讨论如何更好地“整合“ DreamWeaver和Visual Studio.

19.只熟悉System.Web.UI.WebControl和System.Data.SqlClient应该还有一些值得熟悉的类库.

20.零注释
这些都是心里很明白的快手. 一任IDE生成的缺省注释横在那里不管.

21.零事件
对“事件驱动“一无所知. 只知道在Page_Load()里写过程. 或者双击一个按钮写Xxx_Clock()过程. 在他们的程序里看不到event和delegate.

以上是想到哪写到哪, 大家如果碰上让你深恶痛绝的事, 也可以补充.我一直以为, 工作是人品最直接的反映. 对程序员来说, 代码就是最真实的心灵写照.仅仅是个人看法.
9月2日

ASP.NET编程中的十大技巧

1、在使用Visual Studio .NET时,除直接或非引用的对象外,不要使用缺省的名字。
.NET带来的好处之一是所有的源代码和配置文件都是纯文本文件,能够使用NotepadWordPad等任意的文本编辑器进行编辑。如果不愿意,我们并非一定要使用Visual Studio .NET作为集成开发环境。但使用了Visual Studio .NET,我们可以在Windows文件管理器中看到文件,或在Visual Studio .NET之外从文本编辑器中浏览文件的内容。
使用Visual Studio .NET作为集成开发环境有许多好处,其中最显著的好处是它极大地提高了生产效率。使用Visual Studio. NET,我们能够在付出较小代价的情况下更快地开发软件。作为集成开发环境一部分的IntelliSense提供自动的代码完成、在输入方法或函数时提供动态帮助、语法错误的实时提示,以及其他能够提高生产效率的功能。
象其他复杂的工具那样,在学会如何充分发挥它的作用和掌握其习性前,Visual Studio .NET也会使我们产生一种挫折感。有时,它象一个难以了解的黑盒子,会生成大量的文件和许多无用的代码。
Visual Studio .NET的一个功能是,无论是类、控件或表单中的对象,它都能够为新对象提供缺省名字。例如,如果我们创建了一个新的ASP.NET Web Application,其缺省的名字将是WebApplication1。我们可以在新工程对话框中方便地改变该应用的名字,但同时改变的只是该应用程序的名字空间的名字及其所在的虚拟目录,源代码文件的缺省名字仍然是WebForm1.aspxWebForm1.aspx.csC#工程)或WebForm1.aspx.vbVB.NET工程)。

我们可以在方案浏览器中改变ASPX和代码使用的文件名字,但Web页类的名字仍然将是WebForm1。如果在该Web表单上生成一个按钮,其缺省的名字将是Button1。事实上,所有控件的名字都是由控件的类型和数字组成的。
我们能够,也应该将应用程序中所有的表单和控件的名字都修改成有意义的名字。对于较小的演示性程序而言,缺省的名字还能够胜任,但如果应用程序由多个表单,每个表单上有许多按钮和标签时,象frmStartupfrmDataEntryfrmReports这样的表单名就比Form1Form2Form3这样的名字更易于理解和维护。
如果表单上控件要在代码的其他地方引用,使它有一个有意义的名字就更重要了。btnOKbtnCancelbtnPrint这样的名字使看代码的人更容易理解,因而,也比名字为Button1Button2Button3这样的控件更容易维护。
修改一个工程中所有文件中出现的一个名字的一个好方法是,在Visual Studio .NET菜单中依次选择编辑”->“发现和替换”->“替换命令。
在看二周前编写的代码时,我们经常就象第一次见到这些代码一样,因此使它们有一个有助于我们理解其含义的名字是十分有必要的。
2、即使不使用Visual Studio .NET进行编程,使用代码支持文件也有利于提高应用程序的性能
在Web应用程序、Web服务或Web控件等所有的ASP.NET Web工程中,Visual Studio .NET都使用代码支持文件。代码支持文件使工程具有更好的组织、模块性,更适合多人组成的开发团队。另外,它还会带来性能的提高。
代码支持文件的内容被编译成一个组合文件中的类,一般是一个DLL文件,有时也可以是EXE文件。该文件驻留在应用程序的组合体高速缓冲区中,在应用程序启动时,可以立即得到它。
如果代码是包含在<script>标记中或ASPX文件代码中,它仍然会被编译成一个Web页类。在这种情况下,每当该网页在应用程序对话中第一次加载时,都需要重新进行编译,被编译的类就会驻留在内存中。每当计算机启动、IIS停止、重新启动或者源代码、配置文件改变时,该文件必须重新编译。尽管不大,但这样引起的性能损耗也是相当可观的。

3、尽量减少表单回送

每当点击Web网页上的ButtonLinkButtonImageButton控件时,表单就会被发送到服务器上。如果控件的AutoPostBack属性被设置为true,如果CheckBoxCheckBoxList等控件的状态被改变后,也会使表单会发送回服务器。
每次当表单被发送回服务器,就会被重新加载,启动Page_Load事件,执行Page_Load事件处理程序中的所有代码。把网页的初始化代码放在这里是最合适不过的了。我们经常会希望在每次加载网页时执行一些代码,而希望只有在网页第一次加载时执行另一些代码,甚至希望一些代码在除首次加载外的每次加载时执行。
可以利用IsPostBack特性来完成这一功能。在网页第一次加载时,该属性的值是false。如果网页因回送而被重新加载,IsPostBack属性的值就会被设置为true。通过测试,可以在任意时候执行指定的代码。下面是相关的C#代码:
protected void Page_Load(Object sender, EventArgs e)
{
// 网页每次加载时,执行的一些操作
if (!IsPostBack)
{
// 网页第一次加载时执行的操作
}
else
{
// 回送时执行的操作
}

// 网页每次加载时执行的操作
}
我们希望尽量不引起回送(每次回送都会要求服务器进行一系列的操作),即使引起回送后。也希望能够执行尽量少的操作。大规模、浪费时间的操作(例如数据库查找)尤其应当避免,因为它们能够延长应用程序的响应时间。

4、使用StringBuilder

字符串在.NET框架中是不可变的,这意味着改变字符串的操作符和方法会返回字符串的改变后的拷贝,这意味着性能还有提高的空间。当进行大量的字符串操作时,使用StringBuilder类就是一种比较好的选择了。
下面的C#代码测试用二种方式从10000个子字符串中生成字符串所需要的时间。第一次使用了一个简单的字符串串联操作;第二次使用了StringBuilder类。要想查看结果字符串,可以去掉下面的代码中注解行的注解符号:

<%@ Page Language="C#" %>

<script runat="server">
void Page_Load(Object Source, EventArgs E)
{
int intLimit = 10000;
DateTime startTime;
DateTime endTime;
TimeSpan elapsedTime;
string strSub;
string strWhole = "";

// 首先执行字符串连接操作
startTime = DateTime.Now;
for (int i=0; i < intLimit; i++)
{
strSub = i.ToString();
strWhole = strWhole + " " + strSub;
}
endTime = DateTime.Now;
elapsedTime = endTime - startTime;
lblConcat.Text = elapsedTime.ToString();
// lblConcatString.Text = strWhole;

// 使用stringBuilder类进行同样的操作
startTime = DateTime.Now;
StringBuilder sb = new StringBuilder();
for (int i=0; i < intLimit; i++)
{
strSub = i.ToString();
sb.Append(" ");
sb.Append(strSub);
}
endTime = DateTime.Now;
elapsedTime = endTime - startTime;
lblBuild.Text = elapsedTime.ToString();
// lblBuildString.Text = sb.ToString();
}

</script>

<html>
<body>
<form runat="server">

<h1>String Concatenation Benchmark</h1>

Concatenation:
<asp:Label
id="lblConcat"
runat="server"/>

<br/>

<asp:Label
id="lblConcatString"
runat="server"/>

<br/>
<br/>

StringBuilder:
<asp:Label
id="lblBuild"
runat="server"/>

<br/>

<asp:Label
id="lblBuildString"
runat="server"/>

</form>
</body>
</html>
二种方式的差别是相当大的:使用StringBuilder类的Append方法的速度比使用字符串连接的速度快近200倍。比较的结果如下所示:
(图:picture01

5、只在必要时使用服务器端控件

ASP.NET中新引入了一种在服务器端运行的被称作Web Server Controls的控件,在代码中,它们经常通过下面的语法被说明:

<asp:TextBox id="txtLastName" size="40" runat="server" />
它们有时也被称作ASP控件。服务器端控件是由runat属性指示的,它的值总是“server”
通过添加runat属性,一般的HTML控件可以被很方便地转换到服务器端运行,下面是一个简单的例子:

<input type="text" id="txtLastName" size="40" runat="server" />
可以通过id属性中指定的名字,我们可以引用程序中的控件,可以通过编程的方式设置属性和获得值,因此,服务器端处理方式有较大的灵活性。

这种灵活性是有一定代价的。每种服务器端控件都会消耗服务器上的资源。另外,除非控件、网页或应用程序明确地禁止view state,控件的状态是包含在view state的隐藏域中,并在每次回送中都会被传递,这会引起严重的性能下降。
在这方面的一个很好的例子是,网页上控件表格的应用,如果不需要在代码中引用表格中的元素,则使用无需进行服务器端处理的HTML表格。我们仍然可以在HTML表格单元中放置服务器控件,并在代码中引用服务器控件。如果需要引用任意的表格元素,例如指定的单元,则整个表格必须是服务器控件。

6 HyperLink控件、LinkButton控件的差别

对于Web访问者而言,HyperLinkLinkButton控件是一样的,但它们在功能方面仍然有较大的差异。
当用户点击控件时,HyperLink控件会立即将用户导航到目标URL,表件不会回送到服务器上。LinkButton控件则首先将表件发回到服务器,然后将用户导航到目标URL。如果在到达目标URL之前需要进行服务器端处理,则使用LinkButton控件;如果无需进行服务器端处理,则可以使用HyperLink控件。


7
、注释代码

这一技巧并不是针对ASP.NET的,但它是一个良好的编程习惯。
注释不仅仅应当说明代码会执行什么操作,还应当注明原因。例如,不要仅仅在注释中说明是在遍历数组,而是要说明遍历数组是根据某一算法计算一个值,除非算法是相当简单的,否则还应当对算法进行简要的说明。
.NET工程中的不同的编程语言都有各自不同的注释符号,下面是一个简要的说明:
HTML <!-- 注释 -->
javascript // 注释
VBScript ' 注释
VB.NET ' 注释
C# // 注释
/* 多行内容
的注释
*/
SQL -- 注释

在服务器控件的开始和结束标记中没有注释符号,但服务器能够忽略掉所有它不能识别的属性,因此我们能够通过使用没有定义的属性来插入注释。下面是一个例子:

<asp:TextBox
id="txtLastName"
size="40"
comment="这是我的注释"
runat="server" />
在Visual Studio .NET中对源代码进行注释非常简单。高亮度显示需要注释的行,然后按Ctrl+K+C组合键添加注释。要删除注释,只需高亮度显示被注释的代码,并按下Ctrl+K+U组合键。
在C#工程中,我们还可以通过在每行的开始处使用///输入XML注释小节。在注释小节中,我们可以使用下面的XML标记组织注释:
<summary></summary>
<remarks></remarks >
<param></param>
<returns></returns>
<newpara></newpara>
要在Visual Studio .NET中查看这些XML注释的格式化的报告,我们可以首先选择工具菜单项,然后选择建立注释Web网页菜单项。

8
、使用trace方法和trace属性记录Page目录中网页的执行情况

调试程序的一种古老的技术是在程序中的关健点插入输出语句,通常情况下,输出信息中会包含重要变量的值,相关信息可以输出到屏幕、日志文件或者数据库。
在ASP.NET中,通过使用Page命令中的trace属性,这种调试技术的使用更简单了。Page命令是ASPX文件开始处的一行代码,它提供编译器的指示。Page命令中包含一个或多个属性,向编译器提供使用的编程语言、代码支持文件的位置或要继承的类的名字等信息。
Page命令中的属性之一是trace,其值可能是truefalse,下面是一个典型的Page命令,其中的trace属性的值是true

<%@ Page language="c#" trace="true" %>

如果trace属性的值设置为true,由ASPX文件生成的Web页就会显示出来,除了网页本身外,关于该页的大量其他信息也会显示出来。这些信息以下面小节的形式显示在一张表格中:
·Request细节 提供Session ID、请求时间和请求的状态码。
·Trace Information 包含跟踪日志、网页生命周期中按时间先后顺序各个步骤的列表。另外,也可以向其中添加定制信息。
·控件树 以一种分层次的方式列出网页上的所有控件,包括每个控件以字节计算的大小。
·Cookies集合 列出该网页创建的所有Cookie
·头部集合 HTTP头部以及它们的值。
·Server变量 与该网页相关的Server环境变量。

包含在Trace Information小节中的跟踪日志是最有用的,在这里我们可以插入自己的跟踪命令。trace类中有2个方法能够在跟踪日志中插入命令:Trace.WriteTrace.Warn,除了Trace.Warn命令用红色字体显示、Trace.Write命令用黑色字体显示外,它们是相同的。下面是跟踪日志的一个屏幕快照,其中包含有几个Trace.Warn命令。

跟踪日志中最方便的功能是我们可以在开发和测试过程中在整个代码中插入Trace.WriteTrace.Warn语句,而在最终交付应用程序时,可以通过改变Page命令中trace属性的值,禁止这些命令起作用,而无需在部署应用软件前删除这些输出语句。

9、使用存储过程

微软公司的SQL Server和其他现代关系数据库都使用SQL命令定义和处理查询。一个SQL语句或一系列SQL语句提交给SQL ServerSQL Server会对命令进行解析,然后创建一个查询计划并对它进行优化,然后执行该查询计划,这都需要大量的时间。
存储过程是一系列被查询处理器预解析和优化的SQL命令,这些命令会被存储起来,可以得到快速地执行。存储过程也被称作sprocs,它可以接收输入参数,使一个单一的存储过程能够处理较大范围的特定的查询。
因为sprocs是预先被解析的,对于复杂的查询更显得重要,其查询计划是预先优化的,因此调用查询过程比执行相同功能的SQL语句速度要快得多。

10、使用.NET命令行

.NET命令行工具在命令提示符窗口中运行。为了使命令能够执行,它必须驻留在命令提示符的当前目录中,或通过设置PATH环境变量。
.NET SDK启动菜单上安装一个菜单项,该菜单项能够打开一个正确设置了PATH环境变量的命令提示符窗口。我们可以通过依次点击开始”->“程序”->“Microsoft Visual Studio .NET”->“Visual Studio .NET工具”->“Visual Studio .NET命令提示符,启动命令提示符窗口。
通过在将该菜单项从菜单上拖到桌面上时,同时按Ctrl+C键,就可以将该菜单项的快捷方式拷贝到桌面上,使用起来会非常方便。

8月28日

ASP.NET配置文件Web.config

(一).Web.Config是以XML文件规范存储,配置文件分为以下格式
1.配置节处理程序声明
特点: 位于配置文件的顶部,包含在<configSections>标志中。
2.特定应用程序配置
特点: 位于<appSetting>中。 可以定义应用程序的全局常量设置等信息.
3.配置节设置
特点: 位于<system.Web>节中,控制Asp.net运行时的行为.
4.配置节组
特点: 用<sectionGroup>标记,可以自定义分组,可以放到<configSections>内部或其它<sectionGroup>标记的内部.

(二).配置节的每一节
1.<configuration>节
根元素,其它节都是在它的内部.
2.<appSetting>节
此节用于定义应用程序设置项。对一些不确定设置,还可以让用户根据自己实际情况自己设置
用法:
I.
<appSettings>
<add key="Conntction" value="server=192.168.85.66;userid=sa;password=;database=Info;"/>
<appSettings>
定义了一个连接字符串常量,并且在实际应用时可以修改连接字符串,不用修改程式代码.
II.<appSettings>
<add key="ErrPage" value="Error.aspx"/>
<appSettings>
定义了一个错误重定向页面.
3.<compilation>节
格式:
<compilation
defaultLanguage="c#"
debug="true"
/>
I.default language: 定义后台代码语言,可以选择C#和VB.net两种语言.
IIdebug : 为true时,启动aspx调试; 为false不启动aspx调试,因而可以提高应用程序运行
时的性能。 一般程序员在开发时设置为true,交给客户时设置为false.
4.<customErrors>节
格式:
<customErrors
mode="RemoteOnly"
defaultRedirect="error.aspx"
<error statusCode="440" redirect="err440page.aspx"/>
<error statusCode="500" redirect="err500Page.aspx"/>
/>
I.mode : 具有On,Off,RemoteOnly 3种状态。On表示始终显示自定义的信息; Off表示始终显示详细的asp.net错误信息; RemoteOnly表示只对不在本地Web服务器上运行的用户显示自定义信息.
II.defaultRedirect: 用于出现错误时重定向的URL地址. 是可选的
III.statusCode: 指明错误状态码,表明一种特定的出错状态.
IV. redirect:错误重定向的URL.
5.<globalization>节
格式:
<globalization
requestEncoding="utf-8"
responseEncoding="utf-8"
fileEncoding="utf-8"
/>
I.requestEncoding: 它用来检查每一个发来请求的编码.
II.responseEncoding: 用于检查发回的响应内容编码.
III.fileEncoding: 用于检查aspx,asax等文件解析的默认编码.
6.<sessionState>节
格式:
<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
cookieless="false"
timeout="20"
/>
I.mode: 分为off,Inproc,StateServer,SqlServer几种状态
II. stateConnectionString :指定Asp.net应用程序存储远程会话状态的服务器名,默认为本机
III.sqlConnectionString: 当用会话状态数据库时,在这里设置连接字符串
IV. Cookieless: 设置为true时,表示不使用cookie会话状态来标识客户; 否则,相反.
V. TimeOut: 用来定义会话状态存储的时间,超过期限,将自动终止会话.
7.<authentication>节
格式:
<authentication mode="Forms">
<forms name=".ASPXUSERDEMO" loginUrl="Login.aspx" protection="All" timeout="30"/>
</authentication>
<authorization>
<deny users="?"/>
</authorization>
I.Windows: 使用IIS验证方式
II.Forms: 使用基于窗体的验证方式
III.Passport: 采用Passport cookie验证模式
IV.None: 不采用任何验证方式
里面内嵌Forms节点的属性涵义:
I.Name: 指定完成身份验证的Http cookie的名称.
II.LoginUrl: 如果未通过验证或超时后重定向的页面URL,一般为登录页面,让用户重新登录
III.Protection: 指定 cookie数据的保护方式.
可设置为: All None Encryption Validation四种保护方式
a. All表示加密数据,并进行有效性验证两种方式
b. None表示不保护Cookie.
c. Encryption表示对Cookie内容进行加密
d. validation表示对Cookie内容进行有效性验证
IV. TimeOut: 指定Cookie的失效时间. 超时后要重新登录.