[MVC]ASP.NET MVC系列教程

mikel阅读(725)

做为设计模式的王者,MVC在众多领域都成为良好的模型的代名词,前日我们只能靠Monorail来实现ASP.NET的Mvc的而且确ASP.NETMvc已经成为现实
本文只想让大家更直观地认知ASP.NET Mvc,如果语言有所不当,还望先贤海涵,当然,如果文中有所纰漏还希望大家指出
尽量本着对初学者负责的态度来写,但期间的恒心与毅力相信过来的人更加明白,所以如果书写有误希望大家谅解.
ASP.NET MVCASP.NET 3.5 Extensions Preview 的一个部分.
最新的是 ASP.NET MVC Preview on CodePlex.com如果后续文章的书写中版本变化,笔者将在后面文章中进行补充说明.
说明:

  1. 本文的前提环境为.net 3.5,但笔者会尽力写在.net2.0下兼容的程序
  2. 文本中所使用的IDE都为Visual Studio 2008 RTM(中文) 语言基本为C#不过为了方便大家理解 ,也可能会有一些Visual Basic
  3. 笔者计算机操作系统为Windows 2003 std
  4. 笔者将在文中插入少许广告性例程,希望大家不要反感
  5. 其它约定笔者将会后续补充


以下文章属于ASP.NET MVC CodePlex Preview 4



以下文章是属于ASP.NET MVC preview 3


以下文章是属于Asp.net MVC preview 2

相关站点:

[MVC]ASP.Net MVC 开源资源

mikel阅读(815)

ASP.NET mvc ctp版本发布不到一个月时间,在社区出现了丛多的优秀开源项目,社区的活跃性非常高哦,前一段时间园子里也引发了MVCWebForm的讨论,现在给各位推荐几个相关的优秀项目,这些项目是MVC的价值的最佳证明。

1、 ASP.NET mvc Castle MonoRail项目有着直接的渊源关系,第一个是CastleMonorail项目,网站地址: http://www.castleproject.org/ ,建议读读这篇文章:MS MVC框架漩涡中的MonoRail未来 我也在使用WIKI整理castle 的文档:http://www.openbeta.cn/ioc.ashx

2、 NHaml –ASP.NET MVC View Engine,这是一个RubyHaml的版本,对于熟悉Ruby开发的同学一定很熟悉,项目网站http://haml.hamptoncatlin.com/。具体介绍可看这篇文章:http://andrewpeters.net/2007/12/19/introducing-nhaml-an-aspnet-mvc-view-engine

3、 Mvp.Xml Mvp.Xml是一组 Xml LibraryMvp.Xml除了可以让 System.Xml 更好用之外,最主要的是他提早实做许多Microsoft还来不及包在 Framework 里面的 XML 标准的类别,例如:EXSLTXML BaseXIncludeXPointer…等等。Mvp.Xml结合SystemXMLSystem.Xml.Linq 就实现了XsltViewEngine视图引擎,项目网站http://www.codeplex.com/MVPXML

4、 mvccontrib已经有好几个的.NET IOC应用框架Castle Windsor StructureMap Spring.NET Ninject、以及微软Enterprise Library 4.0将支持依赖注入  。这个项目就是整合这些IoC框架以及视图引擎,包括Castle MonoRail所用的NVelocityView视图引擎、NHamlView视图引擎、XsltViewEngine视图引擎等等,如果你有精力和激情,可参与到这个项目的开发,项目地址:http://code.google.com/p/mvccontrib/ 。可阅读如下文章:IoC Container Support for Windsor, StructureMap and Spring.NetJeffrey Palermo在博客里讨论了建立在ASP.NET MVC框架之上的新MVCContrib开源项目,它现在包括了对大多数流行的 .NET IoC工具的Inversion of Control(控制反转)容器的支持
5、Kigg – A Digg like application developed in ASP.NET MVC http://weblogs.asp.net/rashid/archive/2008/02/18/kigg-a-digg-like-application-developed-in-asp-net-mvc.aspx
MVC Contrib已提供4种备选的视图引擎
http://www.infoq.com/cn/news/2008/02/mvc-contrib-view-engines
Using JQuery to add some ajax magic to the ASP.NET mvc framework
http://code.google.com/p/JQuerymvc/
ASP.NET MVC CAPTCHA:ASP.NET MVC中实现CAPTCHA的方法
http://code.google.com/p/coderjournal/
http://www.coderjournal.com/2008/03/actionfilterattribute-aspnet-mvc-captcha/
ASP.NET MVC CSS Sprite
http://weblogs.asp.net/zowens/archive/2008/04/27/asp-net-mvc-css-sprite.aspx

[教程]ASP.Net MVC框架配置与分析

mikel阅读(719)

前几年的时候ASP.NET就有MVC的概念,实际上就是我们熟悉的WebForm开发模型。
1、Model层与视图无关,并且只与数据库相关:
伪代码:
pulic class Model
{
      pulic DataSet ds()
      {
            //数据库库取数据
            return ds;
      }
}
2、Controller实际上就是我们熟悉的Default.aspx.cs文件,继承自System.Web.UI.Page 类的文件
3、View就是aspx文件了
而今,微软推出了新的MVC开发框架,也就是Microsoft ASP.NET 3.5 Extensions。可以从这里下载:http://download.microsoft.com/download/6/5/c/65cad864-54a5-463a-9573-bc7d0bbc1df9/ASPNetExt.exe
当然,安装之前必须安装VS2008。安装完后可以在创建项目的地方增加以下两种项目。
MVCProject.gif
一种是“ASP.NET MVC Web Application and Test”会同时创建MVC项目和一个测试项目,一个是ASP.NET MVC Web Application,只会纯粹的建立MVC项目。而在项目中引用新文件的时候,也会增加MVC的页面。
MVCItem.gif
在创建MVC项目以后,会增加以下文件
MVCPV.gif
访问的机制是通过URL重写实现的。因此,你需要设置IIS映射。MVCIIS.gif
MVC是通过HttpModule进行地址重写的

  <httpModules>
   
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.6.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
   
<add name="DynamicDataModule" type="System.Web.DynamicData.DynamicDataHttpModule, System.Web.Extensions, Version=3.6.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
   
<add name="UrlRoutingModule" type="System.Web.Mvc.UrlRoutingModule, System.Web.Extensions, Version=3.6.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
  
</httpModules>

而在Global.asax.cs中设置了映射关系
   //设置Url重写映射
   //URL格式设置了访问的为controller(这里是Home),action对应HomeController里的方法
   RouteTable.Routes.Add(new Route
   {
    Url = "[controller]/[action]/[id]",
    Defaults = new { action = "Index", id = (string)null },
    RouteHandler = typeof(MvcRouteHandler)
   });

    //设置默认访问地址,因此主目录下看似无用的Default.aspx不能删除掉
    //controller ="Home"设置的是访问的路径,这里对应上图中的Home目录,也对应了HomeController的类名
   //action是对应HomeController.cs类中的Index方法。
   RouteTable.Routes.Add(new Route
   {
    Url = "Default.aspx",
    Defaults = new { controller = "Home", action = "Index", id = (string)null },
    RouteHandler = typeof(MvcRouteHandler)
   });
HomeController.cs代码:
 public class HomeController : Controller
 {
  [ControllerAction]
  public void Index()
  {
   RenderView("Index");
  }

  [ControllerAction]
  public void About()
  {
   RenderView("About");
  }
 }
在HomeController中找到要访问的页面
最后要说明的是Html.ActionLink("About Us", "About", "Test")方法,能够实现自动链接处理,
参数1是 链接显示的文字
参数2是 要访问的文件
参数3是 访问的目录,尽管参数名是controllerName.
全文完。2008年1月18日 by Birdshover
 
http://www.cnblogs.com/birdshover/ 

[专题]ASP.Net上传文件专题

mikel阅读(726)


       本专题从今天开始主要向大家介绍如何实现ASP.NET上传大文件,写这个的目的也主要是为了学习和交流,如果大家发现任何错误,请即时指出,以免误人子弟。本专题主要参考文章:
[1]Asp.NET大文件上传开发总结
[2]ASP.NET 应用程序生命周期概述
[3]SunriseUpload.0.9.1的源码分析(七)
[4]Http 请求处理流程
[5]使用 HtmlInputFile 服务器控件时无法上载大文件
正文部分:

        注意:以下红色部分字体说明该内容引用于微软的相关网站
        因为要做一个视频网站,所以需要提供用户上传视频的功能。可是ASP.NET自带的上传控件只能用于上传小文件,这显然无法满足需要。有些朋友可能要问了 "为什么需要用那个呀,直接FTP传不就好了",是的,用FTP传就方便了很多,但是FTP在用户上传后,无法对上传的文件进行在线编辑(比如格式转换, 添加到数据库呀等),所有这些可以由网站自动完成的烦琐的任务则都将交由管理人员来完成,这对于一个商业网站来说无疑增加了用人成本。而且这些重复的低脑 力活的工作,看起来就和体力活没什么区别,这不又从另一个侧面降低了我们这些IT人员的价值。扯远了,言归正传,那MS为什么要将这个上传控件的能力限制 这么小呢?在MSDN以及微软的其它网站上我们可以了解到:"
web.config 配置文件中的<httpRuntime> 节的 maxRequestLength 参数的默认值为 4096 (4 MB)。所以,默认情况下不能上传大于这个值的文件。这也是为了防止拒绝服务攻击。"

       可是,这样一来就对我们上传大文件造成了麻烦。有些朋友可能发现既然限制上传文件大小是由于maxRequestLength 这个参数,那将这个值改大点不就OK了。的确,这样做便可轻轻松松提高文件上传大小的限制,可是在"
上传过程中,ASP.NET 首先将整个文件加载到内存中,然后用户才可以将该文件保存到磁盘。"也 就是说,如果用户上传的文件大小为100M,那么服务器的内存中就要拿出100M来存放用户上传的文件;如果是10个用户在同时上传,暂且不提并行性的问 题,那10个用户就要占用1000M的内存;如果是100、1000、甚至是几万个用户呢?那么,再大的内存都不够你拿来提供用户上传的。   

        
" 另外,其他因素也会影响可以上载的最大文件大小。这些因素包括可用内存、可用硬盘空间、处理器速度和当前网络流量。对于上载的常规流量的文件, Microsoft 建议您让最大文件大小介于 10 到 20 MB 之间。如果您很少上载文件,则最大文件大小可以为 100 MB。"

        一个企业内部的视频网站,估且算它的日流量为1000人次,那么按照微软的建议,所上传的文件大小应尽量控制在20M以内,可是这样的大小还是很容易造成 服务器的瘫痪,综合考虑后,我把大小控制在6M以内(为什么在这个范围,后面会有提到,提早告诉大家,是为了让文章能连贯一点)。大家一定会奇怪“一般一 部视频大小都至少有个100~200M,小于6M的不多吧?” 是的,这个问题就是我们要解决的关键。

        在解决这个问题前,大家必须先清楚一件事,我们这里所说的文件大小"6M","200M"指的是针对服务器端而言呢,还是客户端而言呢?正确的理解如下: 200M是针对客户端用户而言的大小,一般情况下允许用户上传最大600M大小的文件(这个600M是考虑到我服务器的硬盘大小,大家可以灵活掌握,不过 一般最好不要超过1G);6M则指的是服务器端所能接收的文件大小,这样才能不让服务器的内存因为上传文件而被吞噬光。

        那么,现在我们就可以把问题转化为:如何让服务器以小于6M的大小来接收用户上传的200M视频的?

        大家是不是看得有点晕,那我拿“奥运会门票出售的情况”来举个例子。
        这几天是出售奥运会门票的最后一个阶段,为了能在最后一阶段买到门票,很多人都提早好几天等在售票窗口前。我们假设有10W人需要门票(就好像用户上传 200M的视频),理想的情况自然是开10W个窗口来出售门票(这里的窗口相当于服务器可以接收的文件大小,而10W则相当于我们将 maxRequestLength等相关元素设置很大)。可是想一想就知道,这样做是不可能的(原因自己想吧~)。那怎么解决的呢?只有将窗口数按照某种 规则限制在一定数量(比如20个),然后想买票的人排队买票。

        相信通过这个例子,有些朋友可能已经想到了如何解决我们之前的问题了。办法就是在服务器端通过某种方法将请求分组接收。

[文档]SqlDataSourceEnumerator类

mikel阅读(1055)

提供了一种枚举本地网络内的所有可用 SQL Server 实例的机制。
命名空间:  System.Data.SQL
程序集:  System.Data(在 System.Data.dll 中)
备注
SQL Server 2000 和 SQL Server 2005 都允许应用程序确定当前网络内是否存在 SQL Server 实例。SqlDataSourceEnumerator 类将这些信息向应用程序开发人员公开,提供一个包含有关所有可用服务器的信息的 DataTable。此返回表包含一个服务器实例列表,该列表与用户尝试创建新连接时提供的列表匹配,并在“连接属性”对话框上扩展包含所有可用服务器的下拉列表。
线程安全
此类型的任何公共 static(在 Visual Basic中为 Shared) 成员都是线程安全的。但不保证所有实例成员都是线程

  名称 说明
公共方法 Equals 确定指定的 Object 是否等于当前的 Object。 (继承自 Object。)
受保护的方法 Finalize 允许 Object 在“垃圾回收”回收 Object 之前尝试释放资源并执行其他清理操作。 (继承自 Object。)
公共方法 GetDataSources 检索包含有关所有可见 SQL Server 2000 或 SQL Server 2005 实例的信息的 DataTable。 (重写 DbDataSourceEnumerator..::.GetDataSources()()()。)
公共方法 GetHashCode 用作特定类型的哈希函数。 (继承自 Object。)
公共方法 GetType 获取当前实例的 Type。 (继承自 Object。)
受保护的方法 MemberwiseClone 创建当前 Object 的浅表副本。 (继承自 Object。)
公共方法 ToString 返回表示当前 ObjectString。 (继承自 Object。)

页首

  名称 说明
公共属性 静态成员 Instance 获取 SqlDataSourceEnumerator 的实例,该实例可用于检索有关可用 SQL Server 实例的信息。

详细内容见:

[ORM]利用SqlDataSourceEnumerator获得局域网内的所有SQL Server服

mikel阅读(767)

原来用SQLDMO写了个获得服务器列表的函数,结果只能获得到SQL Server2000的服务器信息,甚至本地的SQL Server2005的信息都获得不到,觉得奇怪于是去google一下,发现了老外用VB.NET写的利用System.Data.Sql.SqlDataSourceEnumerator 获得所有在网的数据库服务器实例的信息代码如下:
地址:http://www.geckoware.com.au/codesnippets/ListSQLServers.txt

Module ListServers
Public Function StServerList() As System.Collections.Generic.List(Of SqlServerInstance)
Dim clsEnumerator As System.Data.Sql.SqlDataSourceEnumerator = System.Data.Sql.SqlDataSourceEnumerator.Instance
Dim clsDataTable As DataTable = clsEnumerator.GetDataSources()
Dim clsServers As New System.Collections.Generic.List(Of SqlServerInstance)
If clsDataTable.Rows.Count > 0 Then
For Each clsRow As DataRow In clsDataTable.Rows
clsServers.Add(New SqlServerInstance(clsRow("ServerName").ToString, clsRow("InstanceName").ToString, clsRow("IsClustered").ToString, clsRow("Version").ToString))
Next clsRow
End If
Return clsServers
End Function
Public Class SqlServerInstance
Private m_sName As String = ""
Private m_sInstance As String = ""
Private m_sClustered As String = ""
Private m_sVersion As String = ""
Public Function ServerName() As String
Return IIf(String.IsNullOrEmpty(m_sInstance), m_sName, m_sName & "\" & m_sInstance).ToString()
End Function
Public Overrides Function ToString() As String
Return m_sName & "\" & m_sInstance & "(" & m_sVersion & ")"
End Function
Public Sub New(ByVal Name As String, ByVal Instance As String, ByVal Clustered As String, ByVal Version As String)
m_sName = Name
m_sInstance = Instance
m_sClustered = IIf(String.IsNullOrEmpty(Clustered), "(Unknown)", Clustered).ToString()
m_sVersion = IIf(String.IsNullOrEmpty(Version), "(Unknown)", Version).ToString()
End Sub
Public ReadOnly Property Name() As String
Get
Return m_sName
End Get
End Property
Public ReadOnly Property InstanceName() As String
Get
Return IIf(String.IsNullOrEmpty(m_sInstance), "Default", m_sInstance).ToString()
End Get
End Property
Public ReadOnly Property Clustered() As String
Get
Return m_sClustered
End Get
End Property
Public ReadOnly Property Version() As String
Get
Return m_sVersion
End Get
End Property
End Class
End Module

于是我用C#重写了一下,代码如下:
类定义:

public class SqlServerInstance
{
private string serverName="";
private string instanceName="";
private string isClusted="";
private string version="";
public SqlServerInstance(string serverName, string instanceName, string isClusted, string version)
{
this.serverName = serverName;
this.instanceName = instanceName;
this.isClusted = isClusted;
this.version = version;
}
}

调用代码:

public void GetServers()
{
SqlDataSourceEnumerator dsEnumerator = SqlDataSourceEnumerator.Instance;
DataTable dtable = dsEnumerator.GetDataSources();
List<SqlServerInstance> ls = new List<SqlServerInstance>();
if (dtable.Rows.Count > 0)
{
cmbServer.Items.Clear();
foreach (DataRow row in dtable.Rows)
{
ls.Add(new SqlServerInstance(row["ServerName"].ToString(),row["InstanceName"].ToString(),row["IsClustered"].ToString(),row["Version"].ToString()));
}
}
}

[数据库]通过SQLDOM获得服务器信息

mikel阅读(895)

获取局域网内SQL Server服务器列表
我简单介绍一下在ASP.NET中如何用SQLDMO来获取SQL Server中的对象信息。首先我们想到的是所在的局域网内有多少SQL Server服务器,知道了服务器,有了登录的用户名和密码,就可以知道在指定的服务器上有多少张表,视图,存储过程,以及每张表中包含的字段信息等。
添加引用sqldmo.dll
安装了SQLServer2000 就有了,在添加引用中找它
最好使用SQL Server 2000的SP3的sqldmo.dll
using SQLDMO;
SQLDMO.ApplicationClass sqlApp = new SQLDMO.ApplicationClass();
SQLDMO.NameList nameList;
int i = 0;
nameList = sqlApp.ListAvailableSQLServers();
for(i=1;iSQLServer中所有的数据库表 SQLDMO.Application sqlApp = new SQLDMO.ApplicationClass(); SQLDMO.SQLServer server = new SQLDMO.SQLServerClass(); server.Connect(Host_ComboBox.Text,UID_Text.Text.Trim(),PWD_Text.Text.Trim()); for(int i=1; i<=server.Databases.Count;i++) { MessageBox.Show(server.Databases.Item(i,"sa").Name); } 1.获取服务器的列表: 获取服务器时,主要是利用了SQLDMO的Application对象,该对象主要有以下几个主要的属性和方法: 方法:ListAvailableSQLServers() 属性:Name SQLServers Properties 示例程序: 1/**////

2 /// 获取局域网内数据库服务器列表
3 ///

4 private void FormatServerList()
5 {
6 sqlServers = sqlApp.ListAvailableSQLServers();
7
8 if(sqlServers != null)
9 {
10 for(int i=0;i 2 /// 连接服务器
3 ///

4 /// 服务器名 5 /// 登录名 6 /// 密码 7 public void Connect(object ServerName,object Login,object Password)
8 {
9
10 }
属性:Databases
Name
Login
Password
QueryTimeOut
在获取数据库列表时,利用它的Databases属性,示例代码如下:
1/**////

2 /// 获取指定服务器的数据库的列表
3 ///

4 private void FormatDatabaseList()
5 {
6 SQLDMO.tSQLServer sr = new SQLDMO.SQLServerClass();
7 sr.Connect(this.wdrp_ServerList.SelectedItem.ToString(),txtUserName,txtUserPwd);
8
9 /**////创建一个DataTable
10 DataTable dt = new DataTable();
11 dt.Columns.Add(“Name”);
12 dt.Columns.Add(“Owner”);
13 dt.Columns.Add(“Size”);
14 dt.Columns.Add(“CreatDate”);
15
16 foreach(Database db in sr.Databases)
17 {
18 if(db.Name != null)
19 {
20 DataRow dr = dt.NewRow();
21
22 /**////获取数据库的名称
23 dr[“Name”] = db.Name;
24
25 /**////获取数据库的所有者
26 dr[“Owner”] = db.Owner;
27
28 /**////获取数据库的大小
29 dr[“Size”] = db.pSize;
30
31 /**////获取数据库的创建日期
32 dr[“CreatDate”] = db.CreateDate;
33
34 dt.Rows.Add(dr);
35 }
36 }
37
38 /**////绑定数据
39 this.wgrd_Database.DataSource = dt;
40 this.wgrd_Database.DataBind();
41 }
3.获取数据中的表的集合:
这时需要创建一个SQLDMO的Database对象,利用它的属性和方法来获取,主要的属性和方法:
方法:Item(object Index,object Owner)
1/**////

2 /// 获取指定项
3 ///

4 /// 索引 5 /// 所有者 6 ///
7 public Database Item(object Index,object Owner)
8 {
9
10 }
属性:Name
Owner
Size
CreateDate
Tables
Views
StoredProcedures
示例代码如下:
1/**////

2 /// 获取指定服务器,指定数据库的表集合
3 ///

4 private void FormatTableList()
5 {
6 SQLDMO.SQLServer sr = new SQLDMO.SQLServerClass();
7 sr.Connect(this.wdrp_ServerList.SelectedItem.ToString(),txtUserName,txtUserPwd);
8
9 /**////创建一个DataTable
10 DataTable dt = new DataTable();
11 dt.Columns.Add(“dbName”);
12 dt.Columns.Add(“Name”);
13 dt.Columns.Add(“Owner”);
14 dt.Columns.Add(“CreatDate”);
15 dt.Columns.Add(“PrimaryKey”);
16
17 for(int j=0;j 2 /// 获取指定项
3 ///

4 /// 索引 5 /// 所有者 6 ///
7 public Table Item(object Index,object Owner)
8 {
9
10 }
属性:Name
Owner
CreateDate
PrimaryKey
Keys
Triggers
Indexs
Rows
Columns
利用这些属性和方法,大家可以很轻松地去获取数据表,字段等信息,这里就不写示例程序了,同样有了这些信息,就可以去写自己的代码生成器了^_^我简单介绍一下在ASP.NET中如何用SQLDMO来获取SQL Server中的对象信息。首先我们想到的是所在的局域网内有多少SQL Server服务器,知道了服务器,有了登录的用户名和密码,就可以知道在指定的服务器上有多少张表,视图,存储过程,以及每张表中包含的字段信息等。
1.获取服务器的列表:
获取服务器时,主要是利用了SQLDMO的Application对象,该对象主要有以下几个主要的属性和方法:
方法:ListAvailableSQLServers()
属性:Name
SQLServers
Properties
示例程序:
1/**////

2 /// 获取局域网内数据库服务器列表
3 ///

4 private void FormatServerList()
5 {
6 sqlServers = sqlApp.ListAvailableSQLServers();
7
8 if(sqlServers != null)
9 {
10 for(int i=0;i 2 /// 连接服务器
3 ///

4 /// 服务器名 5 /// 登录名 6 /// 密码 7 public void Connect(object ServerName,object Login,object Password)
8 {
9
10 }
属性:Databases
Name
Login
Password
QueryTimeOut
在获取数据库列表时,利用它的Databases属性,示例代码如下:
1/**////

2 /// 获取指定服务器的数据库的列表
3 ///

4 private void FormatDatabaseList()
5 {
6 SQLDMO.tSQLServer sr = new SQLDMO.SQLServerClass();
7 sr.Connect(this.wdrp_ServerList.SelectedItem.ToString(),txtUserName,txtUserPwd);
8
9 /**////创建一个DataTable
10 DataTable dt = new DataTable();
11 dt.Columns.Add(“Name”);
12 dt.Columns.Add(“Owner”);
13 dt.Columns.Add(“Size”);
14 dt.Columns.Add(“CreatDate”);
15
16 foreach(Database db in sr.Databases)
17 {
18 if(db.Name != null)
19 {
20 DataRow dr = dt.NewRow();
21
22 /**////获取数据库的名称
23 dr[“Name”] = db.Name;
24
25 /**////获取数据库的所有者
26 dr[“Owner”] = db.Owner;
27
28 /**////获取数据库的大小
29 dr[“Size”] = db.pSize;
30
31 /**////获取数据库的创建日期
32 dr[“CreatDate”] = db.CreateDate;
33
34 dt.Rows.Add(dr);
35 }
36 }
37
38 /**////绑定数据
39 this.wgrd_Database.DataSource = dt;
40 this.wgrd_Database.DataBind();
41 }
3.获取数据中的表的集合:
这时需要创建一个SQLDMO的Database对象,利用它的属性和方法来获取,主要的属性和方法:
方法:Item(object Index,object Owner)
1/**////

2 /// 获取指定项
3 ///

4 /// 索引 5 /// 所有者 6 ///
7 public Database Item(object Index,object Owner)
8 {
9
10 }
属性:Name
Owner
Size
CreateDate
Tables
Views
StoredProcedures
示例代码如下:
1/**////

2 /// 获取指定服务器,指定数据库的表集合
3 ///

4 private void FormatTableList()
5 {
6 SQLDMO.SQLServer sr = new SQLDMO.SQLServerClass();
7 sr.Connect(this.wdrp_ServerList.SelectedItem.ToString(),txtUserName,txtUserPwd);
8
9 /**////创建一个DataTable
10 DataTable dt = new DataTable();
11 dt.Columns.Add(“dbName”);
12 dt.Columns.Add(“Name”);
13 dt.Columns.Add(“Owner”);
14 dt.Columns.Add(“CreatDate”);
15 dt.Columns.Add(“PrimaryKey”);
16
17 for(int j=0;j 2 /// 获取指定项
3 ///

4 /// 索引 5 /// 所有者 6 ///
7 public Table Item(object Index,object Owner)
8 {
9
10 }
属性:Name
Owner
CreateDate
PrimaryKey
Keys
Triggers
Indexs
Rows
Columns
利用这些属性和方法,大家可以很轻松地去获取数据表,字段等信息,这里就不写示例程序了,同样有了这些信息,就可以去写自己的代码生成器了^_^

[ORM]通过序列化和反序列化泛型数据实体集合来实现持久化数据对象的方法

mikel阅读(671)

通过序列化和反序列化泛型数据实体集合来实现持久化数据对象的方法
我们在平时使用数据库的时候,经常会碰到一个问题,就是不希望数据实体对象插入数据库中, 却有想持久化的时候,那么就可以用序列化成
XML字符串,来保存到其他地方,由于生成的是字符串,所以可以保存到任意我们想保存的地方。比如 ASP.NET的ViewState,cookie,cache等。
首先,我们定义一个数据实体类。
class Entity
{
public Entity()
{}
private int id;
public int Id
{
get
{
return id;
}
set
{
id = value;
}
}
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
private double price;
public double Price
{
get
{
return price;
}
set
{
price = value;
}
}
}
于是将他插入到List对象中
List list = new List();
Entity obj = new Entity();
obj.Id = 1;
obj.Name = “test”;
obj.Price = 3.23;
list.Add(obj);
这样,一个List对象就创建成功了,下面我们来将他序列化
public static string Serialize(List GenericList)
{
XmlDocument result = new XmlDocument();
result.LoadXml(““);
foreach (BusinessObject obj in GenericList)
{
XmlElement Item = result.CreateElement(“Item”);
PropertyInfo[] properties = obj.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
if (property.GetValue(obj, null) != null)
{
XmlElement element = result.CreateElement(property.Name);
element.SetAttribute(“Type”, property.PropertyType.Name);
element.InnerText = property.GetValue(obj, null).ToString();
Item.AppendChild(element);
}
}
result.DocumentElement.AppendChild(Item);
}
return result.InnerXml;
}
然后我们调用这个方法
string str = Serialize(list);
生成的XML文件为:


1
test
3.23


下面,我们根据上面生成的xml文件,将他反序列化,生成刚才的List对象
public static List Deserialize(string XmlStr)
{
List result = new List();
XmlDocument XmlDoc = new XmlDocument();
XmlDoc.LoadXml(XmlStr);
foreach (XmlNode ItemNode in XmlDoc.GetElementsByTagName(“Root”).Item(0).ChildNodes)
{
BusinessObject item = Activator.CreateInstance();
PropertyInfo[] properties = typeof(BusinessObject).GetProperties();
foreach (XmlNode propertyNode in ItemNode.ChildNodes)
{
string name = propertyNode.Name;
string type = propertyNode.Attributes[“Type”].Value;
string value = propertyNode.InnerXml;
foreach (PropertyInfo property in properties)
{
if (name == property.Name)
{
property.SetValue(item,Convert.ChangeType(value,property.PropertyType), null);
}
}
}
result.Add(item);
}
return result;
}
然后我们调用这个方法:
List list = Deserialize(str);
完了。
本文只是给大家介绍了序列化List<>对象的简单方法,用的时候要根据自己的情况而定。

[测试]使用NUnit进行单元测试入门

mikel阅读(717)

使用Nunit进行单元测试入门

前言:

Nunit是一项开源的项目,利用Nunit,你可以方便快捷地对已有的.NET组件进行单元测试。利用Nunit,你可以在不修改原有代码的情况下,编写专门的测试代码对需要测试的函数和组件进行测试。如果大家有兴趣可以将NunitVSTS自带的单元测试进行比较:)

正文:

如果你的机器上没有安装Nunit,请先到http://www.nunit.org/download.html下载,并安装到机器上。

接下来,我们来看看究竟如何来使用Nunit进行单元测试

现在,我有这样一个Account类:

namespace bank

{

    public class Account

    {

        private float balance;

        public void Deposit(float amount)

        {

            balance += amount;

        }

        public void Withdraw(float amount)

        {

            balance -= amount;

        }

        public void TransferFunds(Account destination, float amount)

        {

        }

        public float Balance

        {

            get { return balance; }

        }

    }

}

但是我并不知道这个类是否可以正确地工作,所以我需要对Account类进行单元测试。

在可以新建一个类库项目,在这个类库的引用项目中指定Account.dll和Nunit.framework.dll。注意,Nunit.framework.dll文件在你安装Nunit的bin目录下。

然后我在这个新建的类库项目中添加一个AccountTest的类文件后编译,该文件如下:

namespace bank

{

    using NUnit.Framework;

    [TestFixture]

    public class AccountTest

    {

        [Test]

        public void TransferFunds()

        {

            Account source = new Account();

            source.Deposit(200.00F);

            Account destination = new Account();

            destination.Deposit(150.00F);

            source.TransferFunds(destination, 100.00F);

            Assert.AreEqual(250.00F, destination.Balance);

            Assert.AreEqual(100.00F, source.Balance);

        }

    }

}

请注意,这个测试类一定要是public的,否则Nunit无法正常工作。

接 下来,我们启动Nunit(在你的桌面上有快捷方式的图标),然后在File -> Open Project中打开到你刚刚编译出来的AccountTest.dll即可。这个时候,你会发现右边有一个“Run”的按钮可以使用了,点击它,这个时 候,Account类的单元测试就开始了。测试完毕后,出现红色的标志,这是测试失败的标志。这说明我们的Account类有问题,我们需要将 Account类中的Withdraw方法完成:

public void Withdraw(float amount)

{

    balance -= amount;

}

重新编译Account类以后,我们再次点击“Run”按钮,这个时候,红色变成了绿色,这说明测试通过了。

这样,你便完成了对Account类的测试,接下来,我们来详细说一说AccountTest类中奇怪的Attributes

TestFixture

这个Attribute只能在类上使用,他告诉Nunit这个类中包含有需要测试的方法。

不过注意这个类保证一下4点:

1.   这个类必须是Public的。

2.   这个类不能是Abstract的。

3.   这个类必须有一个默认构造函数。

4.   这个类中的方法被标记的Attribute只能出现一次:SetUp, TearDown, TestFixtureSetUp 和 TestFixtureTearDown。

Test

这个Attribute只能标记了TestFixture的类中的方法上使用,他告诉Nunit这个是一个需要测试的方法。

在下来就是AccountTest类中的TransferFunds方法中的Assert

它类似与.NET Framework中的Assert类,如果Assert中的方法返回False,这测试结果为失败,否则为成功。在Nunit中,就是使用Assert来判断一个测试是否通过。

好了,相信现在大家一定对Nunit的使用有了基本的了解了。那么,恭喜大家了。

后记:

Nunit是一个不断完善的免费工具,但是这并代表他比VSTS自带的单元测试工具差,他对VS的支持也是相当不错的,而且可以针对自己对测试的需要来自定义很多功能,同时对插件的支持也给了我们更大的空间来发挥Nunit的功能。

关于更多更详细的介绍,请大家查看Nunit的帮助文档:)

[MVC]ASP.Net MVC Preview4的AJAX支持

mikel阅读(752)

原文地址:http://www.singingeels.com/Articles/AJAX_Panels_with_ASPNET_MVC.aspx

原著作者:Timothy Khouri

翻译:Anders Liu

ASP.NET MVC Preview 4带来了一些AJAX支持,能够适应MVC设计模式的本质。这篇文章向你展示了在ASP.NET MVC中使用“延迟加载AJAX面板”是如何使其变得不可思议的简单。

首先,“ASP.NET AJAX”的问题

由于“Web Froms”(传统的ASP.NET)是基于同时包含了表现层和后台代码的“页面”的,所以ASP.NET AJAX并没有像它本应该的那样光芒四射。很多步入AJAX领域的ASP.NET开发者只是向页面中随意地放置一些“UpdatePanel”来使其“看 上去”支持AJAX。实际上,这只是防止了页面的“闪烁”,而页面还是进行了完整的回发,并且要经历整个页面的生存周期。

这并不是说这些问题是ASP.NET AJAX的责任,而是由是否需要使用完全的AJAX的不同心态造成的。公平地讲,有比UpdatePanel控件更好的ASP.NET AJAX选择。包括:

  • Page Methods——直接调用位于后台代码中(服务器上)的方法。
  • Web Services——调用位于应用程序的Web Services中的方法。

这两种选择比使用UpdatePanel“好”在无需重新加载整个页面,只需向客户端呈现一部分HTML即可。但它们“坏”在你需要使用JavaScript实现所有的表现逻辑(不用别人说也知道这是很恐怖的)。

MVC AJAX给你转机

如果你能得到和使用UpdatePanel一样的ASP.NET呈现能力,并且所有的代码都能分离开,性能也和访问Web Services一样,你会不吃惊吗?来吧,一起感谢MVC设计模式的本质吧——还要感谢ASP.NET MVC——你能!

我们来看一下现实世界中创建“延迟加载”AJAX面板的问题。假设我们有一个Web应用程序,用于向客户端发布一些巨大 的报表。如果我们不使用AJAX,每个报表都会增加页面的整体加载时间。因此,我们将异步地请求每个报表(使用AJAX),是的页面自身能够立即加载,而 每个报表都会在运行完毕后显示出来。

我们将向页面中添加4个“报表”。每个报表都要运行3到5秒。因此如果我们使用传统的Web Forms,这个页面将要加载12到20秒。但由于有了MVC,我们可以将加载时间降低到5秒,并且页面看上去仍然很漂亮。

注意

有很重要的一点需要注意。上面提到的性能收益会受到一些因素的限制。你必须考虑到服务器要处理所有这些请求,这会使最终的结果有所下降。另外,很多浏览器只允许2个并发的下载,因此对于上面的例子,你节省的时间会降低约50%。

使用Ajax.Form方法

MVC Preview 4在“this.Ajax”字段中为所有MVC页面和MVC用户控件添加了一些方法。“Ajax.Form”方法和“Html.Form”方法类似,但它 会添加一些JavaScript来帮助确保可以异步地发送请求。另外,这里还能为应该返回的结果定义一个HTML元素。

例如,如果你想POST诸如“发送邮件”这样的操作,并希望服务器能将“Your email has been sent”这样的文字放在一个ID是“resultDiv”的<div>内,你需要这样做:

  1. <div id="resultDiv"></div>  
  2. <% using (Ajax.Form("SendMail", new AjaxOptions { UpdateTargetId = "resultDiv" })) { %>  
  3.    <!– Your form elements here… –>  
  4. <% } %>  

上面的代码会生成下面的<form>标签:

  1. <form action="/Home/SendMail" onsubmit="Sys.Mvc.AsyncForm.handleSubmit(this, { insertionMode: 0, updateTargetId: 'resultDiv' }); return false;">  
  2.    <!– Your form elements here… –>  
  3. </form>  

和我们前面提到的一样,这非常像“Html.Form”方法生成的form,但你也能清楚地看到“onsubmit”方法被替换为使用AJAX来发送请求,而且你也能看到“resultDiv”参数被传递到服务器了。

服务器会和平常一样接收这个请求,它也会和平常一样发送请求的数据。这个魔术发生在ASP.NET MVC内部。从服务器传回的响应将会放在我们的<div>中,页面的其他部分不会改变。

这是真的,非常简单的AJAX。然而,还必须向你指出一个问题,该表单只在用户明确地点击了提交按钮 (<input type="submit">)“提交”该表单时,它才会与服务器联系。为了解决这个问题,我们需要添加一行JavaScript使其能够自动提交 表单,异步地请求报表。我还对“Form”方法进行了些微改动,添加了一个HTML ID属性,以便我能在JavaScript中访问它。

现在我们新的代码看起来是下面这样:

  1. <div id="resultDiv"></div>  
  2. <% using (Ajax.Form("ReportOne", null,  
  3.       new AjaxOptions { UpdateTargetId = "resultOne" },  
  4.       new { id="reportFormOne" })) { } %>  
  5. <script type="text/javascript">  
  6.    $get("reportFormOne").onsubmit();  
  7. </script>  

提示

如果我直接调用“Sys.Mvc.AsyncForm.handleSubmit”方法,上面的代码还能更简单些。但我选择让MVC为我创建表单,然后通过JavaScript访问它,因此如果JavaScript方法将来发生了变化,我依然能够使用。

看看结果吧!

使用上面的方法,再加上我从Internet上弄来的“loading gif”,我们就有了这样一个页面,它可以动态地(并且是异步地)加载报表,并在可用的时候立即显示给用户。下面是最终结果的一些截图:

这里是上面的项目的源代码。记住,该项目是在ASP.NET MVC Preview 4下编写和编译的,你下载的时候可能已经过时了(译注:真希望它赶紧过时):

此处下载源代码:SingingEels_MVC_Asyncronous_AJAX_Panels.zip