漫漫技术人生路

C#

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  234 随笔 :: 0 文章 :: 30 评论 :: 8 引用

公告

2006年10月19日 #

大家知道在ASP.NET中微软为我们提供了大量的服务器端控件,包括HtmlControl 和WebControl。它们功能强大,为我们的编程提供了极大的方便。更重要的一点是它开放了对第三方控件的使用。这就使我们可以定制自己需要的服务器端控件。
  下面我就以一个集成化的上传组件来说明怎样自定义一个服务器端的控件,这个组件其实是HtmlInputFile、Button 和Label以及事件实现的集合。这个组件要达到的功能是要象已有的webcontrol一样,用一个设定了几个属性的标记就自动可以实现文件上传了,而不用再实现事件等。
  编写后端代码编译成一个dll
  //文件名称:WmjWebControls.cs
  using System.Drawing;
  using System.Web.UI.HtmlControls;
  using System.Web.UI.WebControls;
  using System;
  namespace Wmj
  {
   public class FileUpLoad : Panel
   {
   private HtmlInputFile htmlInputFile;
   private Button button;
   private Label label;
   public FileUpLoad() : base()
   {
   htmlInputFile=new HtmlInputFile();
   button=new Button();
   button.Text="上传";
   button.Click+=new EventHandler(this.Button_Click);
   label=new Label();
   label.Text="<font size=2>请选择上传文件的路径</font>";
   this.Controls.Add(htmlInputFile);
   this.Controls.Add(button);
   this.Controls.Add(label);
   this.Width=450;
   this.Height=30;
   this.BorderStyle=BorderStyle.Dotted;
   this.BorderWidth=1;
   }
   private void Button_Click(object sender, EventArgs e)
   {
   System.Web.HttpPostedFile postedFile=htmlInputFile.PostedFile;
   if(postedFile!=null)
   {
   try{
   string fileName=PathToName(postedFile.FileName);
   if(!fileName.EndsWith(Extension))
   {label.Text="You must select "+Extension+" file!"; return;}
   if(postedFile.ContentLength>int.Parse(FileLength))
   {label.Text="File too big!";return;}
   postedFile.SaveAs(SavePath+fileName);
   label.Text="Upload File Successfully!";
   return;
   }catch(System.Exception exc){label.Text=exc.Message;return;}
   }
   label.Text="Please select a file to upload!";
   return;
   }
   private string savePath="";
   private string extension="";
   private string fileLength="0";
  //上传的文件保存在服务器上的位置默认为c:\ 这些属性一般都是在asp.net的标记中设置也可以在codebehind中设置
   public string SavePath
   {
   get
   {
   if(savePath!="") return savePath;
   return "c:\\";
   }
   set
   {
   savePath=value;
   }
   }
  //上传文件的最大长度 单位k 默认为1k
   public string FileLength
   {
   get
   {
   if(fileLength!="0") return fileLength;
   return "1024";
   }
   set
   {
   fileLength=(int.Parse(value)*1024).ToString();
   }
   }
  //上传文件的扩展名 默认为txt
   public string Extension
   {
   get
   {
   if(extension!="") return extension;
   return "txt";
   }
   set
   {
   extension=value;
   }
   }
   public string PathToName(string path)
   {
   int pos=path.LastIndexOf("\\");
   return path.Substring(pos+1);
   }
   }
  }
  ////////////////////////////////////////////////////////////////////////////////
  ////
  将这个文件编译成dl,l放在要使用位置的bin目录下面就可以在网站中通过
  <Wmj:FileUpLoad SavePath="E:\\" FileLength="3" Extension="txt" runat="server"/>
  使用这个组件了
  下面举个调用这个控件的例子
  <%@page language="C#"%>
  <!--注意下面这一句是必须的-->
  <%@ Register TagPrefix="Wmj" Namespace="Wmj" Assembly="WmjWebControls"%>
  <html>
  <head>
  </head>
  <body>
  <form enctype="multipart/form-data" runat="server">
  <Wmj:FileUpLoad SavePath="E:\\" FileLength="3" Extension="txt" runat="server"/>
  <!--怎么样使用就是这么简单有点一劳永逸的感觉了吧-->
  </form>
  </body>
  </html>
  有了这个例子的启发,大家再也不用担心asp.net的服务器控件太少了吧。
posted @ 2006-10-19 14:29 javaca88 阅读(32) 评论(0) 编辑

http://www.zdnet.com.cn/developer/keywords/TonyPatton
应用开发作为一门学科逐渐成熟,设计模式也成为常见编程问题的解决方案。设计模式为富有经验的开发者提供一种分享他们久经时间考验的方法的途径,帮助每名开发者解决每天遇到的问题。我将探讨如何在开发过程中应用设计模式,并特别强调.NET单态模式。

代码在哪?

设计模式代表处理并解决问题的一种手段,它并不能提供一个解决一切问题的强大代码库,那些认为自己不需要再学习编码的开发者对此会感到很失望。

应用单态模式

.NET单态模式是今天最有常用也最为简单易懂的设计模式之一。尽管它也会有些复杂,但它的基本前提是简单的:只允许建立一个对象的一个实例。此概念适用于许多设计情形。

例如,你可能只有一个处理系统某些方面的计算器类,要维持有效计算,你只想要(或需要)这个对象的一个实例。另外,你可能希望将一个特殊窗体中打开的子窗体数量限制为1个。子窗体可应用一个只允许一个实例的类(由基本窗体衍生出来)。

你可能想了解,你是否可以用一个静态的类或方法达到同样的结果。如果类确实需要存入内存并保持某种状态,单态是一个不错的选择。在计算器类中,你可能倾向于使用一个静态全程变量,但它仅能解决一个问题:全程可访问性。它不能保证在特定时间只运行一个类的一个实例(不是在所有情形下都有必要)。只运行一个类的一个实例的责任应落在类本身,而非类用户身上。

给单态模式编码

在使用单态模式时,要注意以下几个问题:

  • 该类有一个单独的构造器。它是专用的,且不接受参数(接受不同的参数可能会得到不同的结果)。专用的声明可防止其它类对其进行例示,这是对模式的违反。另外,专用的标签可防止子分类。由于子分类允许衍生类建立多个实例,所以这也是必要的。
  • 该类有一个与单独类实例有关的静态变量。
  • 该类有一个普遍有效的静态方法,可访问那个单独类实例。

这些指导方针的焦点在于执行一个单独的类实例。列表A中的C#代码定义了一个应用单态模式的类。列表B中为对应的VB.NET代码。

namespace Patterns {
public sealed class Singleton {
private static readonly Singleton instance = new Singleton();
private int count;
private Singleton() { }
public static Singleton Instance {
get {
return instance;
} }
public int Count {
get { return count++; }
} } }




关于此类的几点提示:

  • 构造器是专用的,因此无法访问,所以用它也不能建立实例。
  • 通用实例方法可访问对象实例。它通过包含实例的静态变量返回对象的唯一实例。
  • 类的密封声明具有很强的破坏力。密封类用来限制面向对象编程的继承功能。一旦一个类被定义为密封类,此类就不能被继承。
  • 计算器变量为专用变量,可通过通用方法进行访问。由于该类只有一个实例,所以该计算器也只有一个实例。


 

可用几种不同的方法给单态模式编码。上面的列表中应用的是一个实例静态对象,它总是存在。如果该对象从未使用,就会形成管理费用。因此,你可以应用列表C中的方法。列表D为对应的VB.NET代码。

public sealed class Singleton2 {
private static readonly Singleton2 instance = null;
private static bool flag = false;
private int count = 0;
private Singleton2() { }
public static Singleton2 GetInstance() {
if (!flag) {
instance = new Singleton2();
flag = true;
}
return instance;
}
public int Count {
get { return count++; }
} }



只有当(如果)GetInstance方法被调用时,第二个实例才会建立对象。因此,如果从不使用对象,就不会建立对象,这样就可节省系统资源。它应用一个静态标记变量来处理对象。

由于总是只有对象的一个实例,因此第一个方法常用来处理线程问题。在第二个实例中,线程可能会引起问题,导致每个线程出现单独实例。你可以进一步应用锁定的方法来控制创建对象,但在本文我们不讨论这个问题。为了保证线程安全,你应使用第二种方法。

结论

设计模式是一个大家熟悉的概念,它一直为开发社区所试验、测试、调整。单态设计模式是一个在应用中提供单一对象访问点的优秀方法。记得在今后的项目中应用单态模式,你可以找到许多适用单态模式的情形。

posted @ 2006-10-19 08:53 javaca88 阅读(48) 评论(0) 编辑

数据库的连接性已经发展成为应用程序开发的一个标准方面。数据库连接字符串现在已经成为每个项目的标准必备条件。我发现自己为了找到所需要的句法,经常要从另外一个应用程序中复制连接字符串或者进行一次搜索。这个在与SQL Server交互操作时更是如此,因为它有太多的连接字符串选项。现在就让我们来研究一下连接字符串的众多方面。

连接字符串

在对象实例化或者建立期间,数据库连接字符串通过属性或方法被传递到必要的对象。连接字符串的格式是一个以分号为界,划分键/值参数对的列表。列表A中包括了一个C#中的例子,说明了怎样用创建SqlConnection对象的方法连接到SQL Server(实际的连接字符串是通过对象的ConnectionString属性分配的)。列表B中包括的是VB.NET的版本。

列表A

string cString = "Data Source=server;Initial Catalog=db;User ID=test;Password=test;";
SqlConnectionconn = new SqlConnection();
conn.ConnectionString = cString;
conn.Open(); 

列表B

Dim cString As String
cString = "Data Source=server;Initial Catalog=db;User ID=test;Password=test;"

Dim conn As SqlConnection = New SqlConnection()
conn.ConnectionString = cString
conn.Open()

连接字符串会指定数据库服务器和数据库,以及访问数据库必需的用户名和密码。但是这种格式并不是对所有数据库交互都适用,它的确有许多可用的选项,其中很多选项都有同义词。

和Data Source(数据源)、Initial Catalog(初始编目)、User ID(用户ID)、和Password(密码)等元素一起,下面这些选项都是可用的:

  • Application Name(应用程序名称):应用程序的名称。如果没有被指定的话,它的值为.NET SqlClient Data Provider(数据提供程序).
  • AttachDBFilenameextended properties(扩展属性)/Initial File Name(初始文件名):可连接数据库的主要文件的名称,包括完整路径名称。数据库名称必须用关键字数据库指定。
  • Connect Timeout(连接超时)/Connection Timeout(连接超时):一个到服务器的连接在终止之前等待的时间长度(以秒计),缺省值为15。
  • Connection Lifetime(连接生存时间):当一个连接被返回到连接池时,它的创建时间会与当前时间进行对比。如果这个时间跨度超过了连接的有效期的话,连接就被取消。其缺省值为0。
  • Connection Reset(连接重置):表示一个连接在从连接池中被移除时是否被重置。一个伪的有效在获得一个连接的时候就无需再进行一个额外的服务器来回运作,其缺省值为真。
  • Current Language(当前语言):SQL Server语言记录的名称。
  • Data Source(数据源)/Server(服务器)/Address(地址)/Addr(地址)/Network Address(网络地址):SQL Server实例的名称或网络地址。
  • Encrypt(加密):当值为真时,如果服务器安装了授权证书,SQL Server就会对所有在客户和服务器之间传输的数据使用SSL加密。被接受的值有true(真)、false(伪)、yes(是)和no(否)。
  • Enlist(登记):表示连接池程序是否会自动登记创建线程的当前事务语境中的连接,其缺省值为真。
  • Database(数据库)/Initial Catalog(初始编目):数据库的名称。
  • Integrated Security(集成安全)/Trusted Connection(受信连接):表示Windows认证是否被用来连接数据库。它可以被设置成真、伪或者是和真对等的sspi,其缺省值为伪。
  • Max Pool Size(连接池的最大容量):连接池允许的连接数的最大值,其缺省值为100。
  • Min Pool Size(连接池的最小容量):连接池允许的连接数的最小值,其缺省值为0。
  • Network Library(网络库)/Net(网络):用来建立到一个SQL Server实例的连接的网络库。支持的值包括: dbnmpntw (Named Pipes)、dbmsrpcn (Multiprotocol/RPC)、dbmsvinn(Banyan Vines)、dbmsspxn (IPX/SPX)和dbmssocn (TCP/IP)。协议的动态链接库必须被安装到适当的连接,其缺省值为TCP/IP。
  • Packet Size(数据包大小):用来和数据库通信的网络数据包的大小。其缺省值为8192。
  • Password(密码)/Pwd与帐户名相对应的密码。
  • Persist Security Info(保持安全信息):用来确定一旦连接建立了以后安全信息是否可用。如果值为真的话,说明像用户名和密码这样对安全性比较敏感的数据可用,而如果值为伪则不可用。重置连接字符串将重新配置包括密码在内的所有连接字符串的值。其缺省值为伪。
  • Pooling(池):确定是否使用连接池。如果值为真的话,连接就要从适当的连接池中获得,或者,如果需要的话,连接将被创建,然后被加入合适的连接池中。其缺省值为真。
  • User ID(用户ID):用来登陆数据库的帐户名。
  • Workstation ID(工作站ID):连接到SQL Server的工作站的名称。其缺省值为本地计算机的名称。
  • posted @ 2006-10-19 08:39 javaca88 阅读(101) 评论(0) 编辑

    由于网络连通性问题,建立数据库连接可能很费时。如果网络出现问题,且数据库资源可用,则连接缓冲池是一个可行的选项。这一主题似乎与我最近谈到的关于处理连接的文章有冲突,但我稍后会在本栏目中解决这个问题。我先讨论一个连接缓冲池,然后说明它在.NET应用程序中的使用方法。

    缓冲池简介

    建立数据库连接分几个步骤。首先,要与网络数据库服务器建立连接。接着,解析连接字符串并对用户进行验证。最后,建立连接并执行操作。连接缓冲池允许应用程序维持一个数据库连接的所有权。

    连接缓冲池维持一组(或一池)活动数据库连接。当一个应用程序试图打开一个数据库连接时,缓冲池(如可用)恢复一个开放的连接。关闭连接则将它返回到缓冲池给其他进程使用。

    ADO.NET缓冲池连接拥有同样的连接或配置(连接字符串)。它能维持一个以上的缓冲池(实际上,每个配置一个缓冲池)。有用的提示:除非另有说明,(默认情况下)程序利用连接缓冲池。如果你关闭或中断所有连接,那么就没有缓冲池(因为没有有效的连接)。

    虽然保持数据库连接一直开放会引起麻烦,但由于这样不必再次打开连接,所以对于应用程序与数据库之间的即时通信会有好处。一些数据库管理员可能并不赞成这一做法,因为数据库同时打开了几个连接(但并非所有连接都有用)。要根据有效的服务器资源与应用程序需求(即是否确实有需要)来应用连接缓冲池。

    应用连接缓冲池

    默认情况下,连接缓冲池处于活动状态。你也可以通过修改连接字符串中的缓冲池设置来撤销默认行为。下面的SQL Server连接字符串并未利用连接缓冲池。

    Data Source=TestServer;Initial Catalog=Northwind;

    User ID=Chester;Password=Tester;Pooling=False;

    其它.NET数据供应者(Data Provider)也可以使用同样的方法。你可以将其值设为真(或除掉Pooling变量使用默认行为)来激活它。另外,连接缓冲池的默认大小为100,但你也可以用连接字符串变量来修改它。你可以用下面的变量来控制缓冲池的最大与最小值,以及事务支持:

    • Max Pool Size:缓冲池允许的最大连接数目。默认值为100。
    • Min Pool Size:缓冲池允许的最小连接数目。默认值为0。
    • Enlist:在建立线程的当前事务中,缓冲池是否自动支持连接的信号。

    下面的SQL Server连接字符串使用了一个连接缓冲池,其最大连接数目为100,最小连接数目为5:

    Data Source=TestServer;Initial Catalog=Northwind;

    User ID=Chester;Password=Tester;Max Pool Size=50;

    Min Pool Size=5;Pooling=True;

    如果你使用.NET Data Provider而非SQL Server,就应该参考文件资料。其他的Data Provider可能拥有更多的缓冲池选项。Oracle Data Provider是一个典型的例子,它提供两个控制连接池缩小或增大的选项——Decr Pool Size和Incr Pool Size。

    微软文件规定,连接缓冲池通过对释放出缓冲池的连接进行再分配,从而满足连接需求。如果缓冲池已达到最大,且没有可用的连接,则请求排队等候。在超时时间(默认为15秒)到达前,缓冲池会设法回收利用连接。如果在连接超时前,缓冲池无法满足需求,就会产生异常。

    缓冲池使用建议

    使用连接缓冲池时应保持谨慎。以下是使用时的几点提示:

    • 只有在需要时才打开连接。也就是说,及时打开连接。所以,要在需要时打开连接,不早也不晚。还有,操作完成后立即关闭连接,不要等到垃圾收集器来关闭连接。
    • 在关闭相关连接前,关闭用户定义的事务。
    • 要维持连接缓冲池,必须保持至少开放一个连接。因此,不要关闭缓冲池中的所有连接。如果服务器资源出现问题,你可以关闭所有连接;那么,下一个请求将重建缓冲池。
    • 在采用集成安全机制时,不要使用连接缓冲池。这样做会为每个用户建立一个独特的连接字符串,于是每个用户拥有一个连接缓冲池,但其他用户却不能使用。最终使性能降低,所以在这种情况下要避免使用缓冲池。

    ADO.NET 2.0

    ADO.NET 2.0推出了两个与连接缓冲池有关的新方法——ClearAllPools和ClearPool。ClearAllPools为一个指定的提供者清除连接缓冲池;ClearPool则清除与特定连接有关的连接缓冲池。如果在调用上述两个方法时,有连接在使用之中,则对它们打上适当的标记。当连接关闭后,就将它们抛弃,而不是返回到缓冲池中。

    其它应用选项

    整理数据库资源专栏后,是一个简述连接缓冲池的专栏,这似乎有些奇怪。问题的关键在于了解可用的连接,并根据应用程序需求对它们加以应用。如果应用程序与数据库保持即时通信,那么连接缓冲池就成为最佳选择,因为此时不需要打开/建立连接,性能也因此得到提高。另一方面,夜晚运行的应用程序不必维持缓冲池,因为它在白天时不需要数据库。在决定是否应用连接缓冲池时,做出明智的判断。

    posted @ 2006-10-19 08:37 javaca88 阅读(532) 评论(0) 编辑