[文档]SqlDataSourceEnumerator类

mikel阅读(1130)

提供了一种枚举本地网络内的所有可用 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阅读(783)

原来用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阅读(909)

获取局域网内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;i 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阅读(685)

通过序列化和反序列化泛型数据实体集合来实现持久化数据对象的方法
我们在平时使用数据库的时候,经常会碰到一个问题,就是不希望数据实体对象插入数据库中, 却有想持久化的时候,那么就可以用序列化成
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阅读(797)

使用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阅读(756)

原文地址: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

[C#]C#中的自定义属性

mikel阅读(1163)

原著:Sadaf Alvi
翻译:Abbey

 

原文出处 Attributes in C# CodeProject
摘要
  在这篇指南里,我们将会看到如何自己创建属性(Attribute),并将其用到不同的程序实体(Entity)上,在程序运行时获取属性信息。
译注
  MSDN将 Attribute 与 Property 均译作“属性”。我真不知道该怎么译了,就将 Property 译作“数据属性”吧。
介绍
  属性(Attribute)是一种新型的声明信息。我们可以使用属性来定义设计时的信息(比如帮助文件、文档的链接),以及运行时的信息(比如将一个 类的域与一个XML的域相关联)。我们也可以用属性来创建“自描述”的组件(可以提供该组件的描述信息)。在这篇指南里,我们将会看到如何自己创建属性 (Attribute),并将其用到不同的程序实体(Entity)上,并在程序运行时获取属性信息。
属性的概念
  MSDN(ms-help://MS.MSDNQTR.2002APR.1033/csspec/html/vclrfcsharpspec_17_2.htm)里是这样定义的:属性是一个声明的附加声明。
使用预定义的属性
  C#已经预定义了一小组的属性供我们使用。在学习如何创建一个自定义的属性前,我们先通过一段代码来看看怎么使用这些预定义的属性吧。

using System;
public class AnyClass
{
[Obsolete("别用Old这个老方法了,请用New方法", true)]
static void Old( ) { }
static void New( ) { }
public static void Main( )
{
Old( );
}
}      

在这个例子里我们使用了Obsolete(“陈旧的”)属性,它会将其所修饰的程序实体(类、方法、数据成员等)说明为已废弃不用的。第一个参数—一 个字符串说明这个实体为何被废弃、由谁代替。实际上这个字符串的内容你想写什么都可以。第二个参数则告诉编译器将用户对此实体的调用视作一个编译错误。这 个参数的缺省值为false,表示编译器仅将用户对其的调用视作警告。编译上面这段代码时,我们将会得到一个编译错误(译注:注意编译错误后附的提示了 吗?):

AnyClass.Old() is obsolete:“别用Old这个老方法了,请用New方法”

开发自定义的属性
  现在开始开发我们自己的属性吧。这儿有一个小窍门:从C#定义的System.Attribute类派生我们的属性类(从抽象基类 System.Attribute直接或间接地派生一个类,该派生类都是一个属性类。一个属性类的声明就定义了一种新的属性类型),然后得到了这样一个声 明:

using System;
public class HelpAttribute : Attribute
{
}

不管你相不相信,我们已经创建了一个自定义的属性。我们可以象这样用它修饰任何的类:

[Help()]
public class AnyClass
{
}

注意:
  
在 属性类名与后缀Attribute间存在一个自动的编译转换。因此当我们用一个属性去修饰一个程序实体时,不需要给出Attribute这个后缀。编译器 首先会在System.Attribute的所有派生类中进行匹配,如果没有找到匹配属性,它就将属性名加上Attribute后缀名后再进行匹配。   
  目前我们的这个属性还没什么用,让我们加点内容吧。在这个示例里,我们为自定义的属性类添加了一个数据属性Description(Property),我们将在本文的最后演示如何在运行时查询这些信息。

using System;
public class HelpAttribute : Attribute
{
public HelpAttribute(String Descrition_in)
{
this.description = Description_in;
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
}
[Help("这是个什么也不做的类")]
public class AnyClass
{
}

定义/控制自定义属性的使用
  AttributeUsage 类是另一个预定义的属性类,以帮助我们控制自定义属性的使用。亦即我们可以定义自定义属性类的属性。这个类描述了如何使用自定义的属性类。AttributeUsage有三个数据属性可用以修饰我们的自定义的属性:

ValidOn

定义了自定义属性在哪些程序实体上可被使用。这个可使用实体的列表可通过AttributeTargets枚举类型的OR操作进行设置
AllowMultiple 定义了是否可在同一个程序实体上同时使用多个属性进行修饰
Inherited 定义了自定义属性的修饰是否可由被修饰类的派生类继承

  让我们做点具体的吧。我们将会用一个AttributeUsage属性修饰我们的属性类,以控制其作用范围:

using System;
[AttributeUsage(AttributeTargets.Class), AllowMultiple = false, Inherited = false ]
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this.description = Description_in;
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
}

先看看AttributeTargets.Class,说明了我们的Help属性只能用以修饰类,下面的这段代码将会导致一个编译错误(“属性 Help不能用在这样的声明上,它只能用在类的声明上”),因为我们用Help属性去修饰方法AnyMethod()了:

[Help("this is a do-nothing class")]
public class AnyClass
{
[Help("this is a do-nothing method")]    //error
public void AnyMethod()
{
}
}

编译错误:

AnyClass.cs: Attribute ''Help'' is not valid on this declaration type.
It is valid on ''class'' declarations only.

当然我们可以AttributeTargets.All来允许Help属性修饰任何类型的程序实体。AttributeTargets可能的值包括:

  • Assembly,
  • Module,
  • Class,
  • Struct,
  • Enum,
  • Constructor,
  • Method,
  • Property,
  • Field,
  • Event,
  • Interface,
  • Parameter,
  • Delegate,
  • All = Assembly | Module | Class | Struct | Enum | Constructor | Method | Property | Field | Event | Interface | Parameter | Delegate,
  • ClassMembers = Class | Struct | Enum | Constructor | Method | Property | Field | Event | Delegate | Interface )

接下来,该看看AllowMultiple = false这句了:它确定了不能象下面这样,在同一实体上同时使用多个同种属性进行修饰:

[Help("this is a do-nothing class")]
[Help("it contains a do-nothing method")]
public class AnyClass
{
[Help("this is a do-nothing method")]        //这也是错误的,因为Help属性只能修饰类
public void AnyMethod()
{
}
}

编译错误:

      AnyClass.cs: Duplicate ''Help'' attribute

我们再来谈谈AttributeUsage的最后一个数据属性Inherited:定义了自定义属性的修饰是否可由被修饰类的派生类继承。基于下示代码表示的继承关系,让我们看看会发生什么吧:

[Help("BaseClass")]
public class Base
{
}
public class Derive :  Base
{
}

我们选择了AttributeUsage的四种组合:

  • [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false ]
  • [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false ]
  • [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true ]
  • [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true ]

对应上述组合的结果:

  1. 如果我们查询(稍后我们会看见如何在运行时查询一个类的属性信息。)这个Derive类的Help属性时,会因其未从基类继承该属性而一无所获。
  2. 因为同样的原因,得到与结果一同样的结果。
  3. 为了解释这后面的两种情况,我们把同样的属性也用在这个Derive派生类上,代码修改如下:
  4. [Help("BaseClass")]
    public class Base
    {
    }
    [Help("DeriveClass")]
    public class Derive :  Base
    {
    }
  5. 我们的查询会同时得到其类Base与派生类Dervie的Help属性信息,因为继承与多重修饰均被允许。

注意:
  
AttributeUsage只能用于System.Attribute的派生类,且该派生类的AllowMultiple与Inherited都为false。
定位参数与命名参数   
  定位参数是属性类构造子(Constructor)的参数。它们是每次使用该属性修饰某个程序实体时都必须提供值的参数。相对的,命名参数则是可选参 数,它也不是属性类构造子的参数。为了详细解释它们的含义,让我们给Help属性类加点内容,然后看看下面的示例:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this.description = Description_in;
this.verion = "No Version is defined for this class";
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
protected String version;
public String Version
{
get
{
return this.version;
}
//即便我们不想我们的属性用户设置Version这个数据属性,我们也不得不提供set方法
set
{
this.verion = value;
}
}
}
[Help("This is Class1")]
public class Class1
{
}
[Help("This is Class2", Version = "1.0")]
public class Class2
{
}
[Help("This is Class3", Version = "2.0",
Description = "This is do-nothing class")]
public class Class3
{
}

我们查询Class1的Help属性信息时,会得到下列结果:

Help.Description : This is Class1
Help.Version :No Version is defined for this class

如果我们不定义Version数据属性的值,那么构造子函数体内所赋的缺省值将会使用。如果也没有,那么该数据属性对应的数据类型的缺省值将被使用(比如int类型的缺省值为0)。查询Class2将会得到这样的结果:

Help.Description : This is Class2
Help.Version :  1.0

请不要为了可选的参数而提供多个构造子的重载版本,而应该将它们定义成命名参数。我们之所以称其为“命名的”,是我们为了能在构造子里给 它们赋值,不得不用一个个的标识符定义和访问它们。比如在第二个类中Help属性的使用[Help("This is Class2", Version = "1.0")] 你瞧,AttributeUsage的ValidOn参数就是一个定位参数,而Inherited与AllowMultiple则是命名参数。   注意:在属性类的构造子中给命名参数赋值,我们必须为它提供一个相应的set方法,否则会导致这样的编译错误(Version不能是一个只读的数据属 性):

''Version'' : Named attribute argument can''t be a read only property

当我们查询Class3的Help属性信息时会发生什么呢?会这样-因上述的原因导致编译错误(Description不能是只读的数据属性):

''Desciption'' : Named attribute argument can''t be a read only property

所以还是给Description添加一个set方法吧。这样会得到正确的输出结果:

This is do-nothing class
Help.Version : 2.0

这是因为构造子利用定位参数构造一个属性时,它会调用所有命名参数的set方法。构造子里的赋值行为实际均由各命名参数对应的数据属性的set方法完成,被其覆写(Override)了。
参数类型
  一个属性类的参数可使用的数据类型限于:

  • bool
  • byte
  • char
  • double
  • float
  • int
  • long
  • short
  • string
  • System.Type
  • object
  • 枚举类型以及上述数据类型的一维数组

属性标识
  让我们想象一下,怎么才能把我们的Help属性用到一个完整的程序集(assembly)上?首先要面对的问题是该把Help属性放在哪儿,以便让编 译器识别出它是属于一个程序集的?再考虑另一种情况:我们想把一个属性用在某个方法的返回类型上时,编译器如何才能确定我们把它用在了返回类型而不是这个 方法本身之上?要解决这么多含糊的问题,我们需要属性标识。借助属性标识的帮助,我们可以明确地告诉程序集我们希望把属性放在哪儿。比如:

[assembly: Help("this a do-nothing assembly")]

这个Help属性前的assembly标识符显式地告诉了编译器,当前这个Help属性用于整个程序集。可用的标识符包括:

  • assembly
  • module
  • type
  • method
  • property
  • event
  • field
  • param
  • return

在运行时查询属性   
  我们已经知道了如何创建属性并如何在程序中使用它们。现在该学习我们所建属性类的用户如何才能在运行时查询该属性类的信息了。要查询一个程序实体的所有属性信息,我们得使用反射(reflection)-在运行时发现类型信息的一种功能。
  我们可以直接使用.NET Framework提供的反射Reflection API来枚举一个完整程序集的所有元数据(metadata),并产生该程序集所有类、类型、方法的列表。还记得之前的Help属性和AnyClass类吗?

using System;
using System.Reflection;
using System.Diagnostics;
//attaching Help attribute to entire assembly
[assembly : Help("This Assembly demonstrates custom attributes creation and their run-time query.")]
//our custom attribute class
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this.description = Description_in;
}
protected String description;
public String Description
{
get
{
return this.deescription;
}
}
}
//attaching Help attribute to our AnyClass
[HelpString("This is a do-nothing Class.")]
public class AnyClass
{
//attaching Help attribute to our AnyMethod
[Help("This is a do-nothing Method.")]
public void AnyMethod()
{
}
//attaching Help attribute to our AnyInt Field
[Help("This is any Integer.")]
public int AnyInt;
}
class QueryApp
{
public static void Main()
{
}
}

我们将在接下来的两节里在我们的Main方法里加入属性查询的代码。
查询程序集的属性   
  在接下来的代码片段里,我们获取当前进程的名字,并使用Assembly类的LoadFrom方法装载程序集。然后我们使用 GetCustomAttributes方法获取当前程序集的所有自定义属性。接下来的foreach语句又遍历所有的属性对象,并试着将这些属性转化为 Help属性(使用as关键字进行转换,如果转换失败,将会返回一个空值而不是触发一个异常)。再后的一条语句是指如果转换成功,则显示Help属性的所 有数据属性信息。

class QueryApp
{
public static void Main()
{
HelpAttribute HelpAttr;
//Querying Assembly Attributes
String assemblyName;
Process p = Process.GetCurrentProcess();
assemblyName = p.ProcessName + ".exe";
Assembly a = Assembly.LoadFrom(assemblyName);
foreach (Attribute attr in a.GetCustomAttributes(true))
{
HelpAttr = attr as HelpAttribute;
if (null != HelpAttr)
{
Console.WriteLine("Description of {0}:\n{1}", assemblyName,HelpAttr.Description);
}
}
}
}

程序的输出结果:

Description of QueryAttribute.exe:
This Assembly demonstrates custom attributes creation and
their run-time query.
Press any key to continue

查询类、方法和域的属性
  在下面的代码片段里,和上面的代码不同的只是Main方法的第一条语句变成了:

Type type = typeof(AnyClass);

它使用typeof操作符返回AnyClass对应的Type对象。其余的代码也类似上述的代码,我想不需要再做解释了吧。要查询方法和域的属性,我们首先要获得当前类中所有方法和类,然后再用类似于查询类的属性的方法来查询与之对应的属性。

class QueryApp
{
public static void Main()
{
Type type = typeof(AnyClass);
HelpAttribute HelpAttr;
//Querying Class Attributes
foreach (Attribute attr in type.GetCustomAttributes(true))
{
HelpAttr = attr as HelpAttribute;
if (null != HelpAttr)
{
Console.WriteLine("Description of AnyClass:\n{0}",
HelpAttr.Description);
}
}
//Querying Class-Method Attributes
foreach(MethodInfo method in type.GetMethods())
{
foreach (Attribute attr in method.GetCustomAttributes(true))
{
HelpAttr = attr as HelpAttribute;
if (null != HelpAttr)
{
Console.WriteLine("Description of {0}:\n{1}",
method.Name,
HelpAttr.Description);
}
}
}
//Querying Class-Field (only public) Attributes
foreach(FieldInfo field in type.GetFields())
{
foreach (Attribute attr in field.GetCustomAttributes(true))
{
HelpAttr= attr as HelpAttribute;
if (null != HelpAttr)
{
Console.WriteLine("Description of {0}:\n{1}",
field.Name,HelpAttr.Description);
}
}
}
}
}

下面是程序输出:

Description of AnyClass:
This is a do-nothing Class.
Description of AnyMethod:
This is a do-nothing Method.
Description of AnyInt:
This is any Integer.
Press any key to continue

关于作者
Sadaf Alvi,卡拉奇大学的自然科学学士,主页http://www24.brinkster.com/salvee

[原创]C#自定义属性应用

mikel阅读(882)

C#的自定义属性就是Java中的Metadata,最近一直在鼓捣自己的C#的持久化架构,用到了对表中的字段标示,于是用了Java中Hibernate的解决办法,加入了自定义属性到持久化类的属性上,用于查询时候获得字段以及表的名称进行对应,代码如下:
1.声明自定义属性:

[AttributeUsage(AttributeTargets.Property,Inherited=true,AllowMultiple=false)]
public class Sel&#101;ctParameterAttribute : Attribute
{
private string parameter;
public Sel&#101;ctParameterAttribute(string param)
{
this.parameter = param;
}
public string GetParameter()
{
return this.parameter;
}
}

2.使用自定义属性定义实体类

public class Area
{
[Sel&#101;ctParameterAttribute("@Identifier")]
public int Identifier { get; set; }
[Sel&#101;ctParameterAttribute("@AreaName")]
public string AreaName { get;set;}
}

3.获得自定义属性:

Area area = new Area();
PropertyInfo prop = typeof(Area).GetProperty("Identifier");
Object[] objs=prop.GetCustomAttributes(true);
//Console.Write();
//Object[] attrs =typeof(Area).GetCustomAttributes(true);
Console.Write("objs:{0}",attrs.Length);
foreach (Object attr in attrs)
{
if (attr is Sel&#101;ctParameterAttribute)
{
Sel&#101;ctParameterAttribute a = (Sel&#101;ctParameterAttribute)attr;
Console.Write("param:{0}",a.GetParameter());
}
}

[原创]C#执行分页查询且有OUTPUT参数的存储过程

mikel阅读(968)

1.实例表代码

/****** 对象:  Table [dbo].[Test]    脚本日期: 07/25/2008 10:37:05 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Cr&#101;ate TABLE [dbo].[Test](
[Identifier] [int] IDENTITY(1,1) NOT NULL,
[Name] [nchar](10) COLLATE Chinese_PRC_90_CI_AI NULL,
[Alias] [nvarchar](50) COLLATE Chinese_PRC_90_CI_AI NULL,
[Texts]  COLLATE Chinese_PRC_90_CI_AI NULL,
[Price] [decimal](18, 0) NULL,
[Cr&#101;ateDate] [datetime] NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
[Identifier] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

2.存储过程代码

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
-- =============================================
-- Author:		<Author,,Name>
-- Cr&#101;ate date: <Cr&#101;ate Date,,>
-- Description:	<Description,,>
-- =============================================
Alt&#101;r PROCEDURE [dbo].[TestSel&#101;ct]
@PageSize int=0,
@CurrentPage int=1,
@TotalPage int OUTPUT,
@Identifier int=null,
@Name nchar(10)=null,
@Alias nvarchar(50)=null,
@Texts text=null,
@Price decimal(18,0)=null,
@Cr&#101;ateDate datetime=null
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with Sel&#101;ct statements.
SET NOCOUNT ON;
--设置字符型的查询Like
SET @Name = &#39;%&#39;+RTRIM(@Name) + &#39;%&#39;
SET @Alias=&#39;%&#39;+RTRIM(@Alias)+&#39;%&#39;
--判断是否进行分页
IF (@PageSize>0)
BEGIN
--取得总页数
Sel&#101;ct @TotalPage=Count(Identifier) FROM Test Wh&#101;re
(@Identifier is null o&#114; Identifier=@Identifier)
and (@Name is null o&#114; Name like @Name)
and (@Alias is null o&#114; Alias like @Alias)
and (@Texts is null o&#114; Texts like @Texts)
and (@Price is null o&#114; Price=@Price)
and (@Cr&#101;ateDate is null o&#114; Cr&#101;ateDate=@Cr&#101;ateDate)
--进行页数加1
IF(@TotalPage>Round(@TotalPage,0))
BEGIN
--大于当前页面+1
SET @TotalPage=Round(@TotalPage,0)+1
END
ELSE
BEGIN
SET @TotalPage=Round(@TotalPage,0)
END
--执行分页查询
Sel&#101;ct TOP (@PageSize) Identifier,Name,Alias,Texts,Price,Cr&#101;ateDate FROM Test
Wh&#101;re Identifier NOT IN (
Sel&#101;ct Top (@PageSize*(@PageSize-1))Identifier
FROM Test
Wh&#101;re
(@Identifier is null o&#114; Identifier=@Identifier)
and (@Name is null o&#114; Name like @Name)
and (@Alias is null o&#114; Alias like @Alias)
and (@Texts is null o&#114; Texts like @Texts)
and (@Price is null o&#114; Price=@Price)
and (@Cr&#101;ateDate is null o&#114; Cr&#101;ateDate=@Cr&#101;ateDate)
)
and
(@Identifier is null o&#114; Identifier=@Identifier)
and (@Name is null o&#114; Name like @Name)
and (@Alias is null o&#114; Alias like @Alias)
and (@Texts is null o&#114; Texts like @Texts)
and (@Price is null o&#114; Price=@Price)
and (@Cr&#101;ateDate is null o&#114; Cr&#101;ateDate=@Cr&#101;ateDate)
END
ELSE
BEGIN
-- Ins&#101;rt statements for procedure here
Sel&#101;ct Identifier,Name,Alias,Texts,Price,Cr&#101;ateDate
FROM Test
Wh&#101;re
(@Identifier is null o&#114; Identifier=@Identifier)
and (@Name is null o&#114; Name like @Name)
and (@Alias is null o&#114; Alias like @Alias)
and (@Texts is null o&#114; Texts like @Texts)
and (@Price is null o&#114; Price=@Price)
and (@Cr&#101;ateDate is null o&#114; Cr&#101;ateDate=@Cr&#101;ateDate)
END
END

3.C#调用存储过程代码

SqlCommand cmd = new SqlCommand();
SqlConnection cn = new SqlConnection(connectionString);
cn.Open();
cmd.Connection = cn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "TestSel&#101;ct";
cmd.Parameters.Add(new SqlParameter("@PageSize", 1));
cmd.Parameters.Add(new SqlParameter("@CurrentPage",1));
cmd.Parameters.Add(new SqlParameter("@TotalPage",SqlDbType.Int));
cmd.Parameters["@TotalPage"].Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
Console.Write("totalPage:{0}",cmd.Parameters["@TotalPage"].Value.ToString());
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.Write("totolPage:{0}",reader[6]);
}
Console.Read();

[代码]C#获得存储过程输出参数值

mikel阅读(850)

11.获取Return返回值 
 2
 3
 4程序代码 
 5//存储过程 
 6//Create PROCEDURE MYSQL 
 7//    @a int, 
 8//    @b int 
 9//AS 
10//    return @a + @b 
11//GO 
12SQLConnection conn = new SQLConnection(ConfigurationManager.ConnectionStrings["LocalSQLServer"].ToString()); 
13conn.Open(); 
14SqlCommand MyCommand = new SqlCommand("MYSQL", conn); 
15MyCommand.CommandType = CommandType.StoredProcedure; 
16MyCommand.Parameters.Add(new SqlParameter("@a", SqlDbType.Int)); 
17MyCommand.Parameters["@a"].Value = 10
18MyCommand.Parameters.Add(new SqlParameter("@b", SqlDbType.Int)); 
19MyCommand.Parameters["@b"].Value = 20
20MyCommand.Parameters.Add(new SqlParameter("@return", SqlDbType.Int)); 
21MyCommand.Parameters["@return"].Direction = ParameterDirection.ReturnValue; 
22MyCommand.ExecuteNonQuery(); 
23Response.Write(MyCommand.Parameters["@return"].Value.ToString()); 
24
252.获取Output输出参数值 
26
27
28程序代码 
29//存储过程 
30//Create PROCEDURE MYSQL 
31//    @a int, 
32//    @b int, 
33//    @c int output 
34//AS 
35//    Set @c = @a + @b 
36//GO 
37SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSQLServer"].ToString()); 
38conn.Open(); 
39SqlCommand MyCommand = new SqlCommand("MYSQL", conn); 
40MyCommand.CommandType = CommandType.StoredProcedure; 
41MyCommand.Parameters.Add(new SqlParameter("@a", SqlDbType.Int)); 
42MyCommand.Parameters["@a"].Value = 20
43MyCommand.Parameters.Add(new SqlParameter("@b", SqlDbType.Int)); 
44MyCommand.Parameters["@b"].Value = 20
45MyCommand.Parameters.Add(new SqlParameter("@c", SqlDbType.Int)); 
46MyCommand.Parameters["@c"].Direction = ParameterDirection.Output; 
47MyCommand.ExecuteNonQuery(); 
48Response.Write(MyCommand.Parameters["@c"].Value.ToString());