65.9K
CodeProject 正在变化。 阅读更多。
Home

在 SqlDataSource Select 命令中使用 Oracle 存储过程

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.60/5 (7投票s)

2009年1月5日

CPOL

1分钟阅读

viewsIcon

70359

downloadIcon

440

如何在 SqlDataSource Select 命令中使用 Oracle(以及其他非 Microsoft)SP

引言

在 SqlDataSource Select 命令中使用 Oracle 存储过程并非易事。 当你从 Oracle SP 返回记录集时,你必须声明一个类型为 sys_refcursorout 参数,这需要在数据源上处理 Selecting 事件才能实现。

背景

为此,我将演示两种方法,一种使用简单的代码后台处理 Selecting 事件,另一种是开发自定义 Parameter 控制,并对 SqlDataSource 控制进行子类化。 后者更复杂,但它使你能够使用不仅来自 Oracle,而且来自所有返回游标的存储过程的数据库中的存储过程。

在代码后台中使用 Selecting 事件

首先,我们需要创建将从我们的应用程序调用的简单存储过程

create or replace procedure testCountries(p_rc out sys_refcursor) is
begin
       open p_rc for 
       select * from Countries;
end testCountries;

要从 ASP.NET 页面访问此 SP,你可以创建一个如下页面

<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1">
</asp:GridView>
        
        <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
            ConnectionString="<%$ ConnectionStrings:oraConnectionString %>" 
            ProviderName="<%$ ConnectionStrings:oraConnectionString.ProviderName %>" 
            SelectCommand="TESTCOUNTRIES" SelectCommandType="StoredProcedure" 
            onselecting="SqlDataSource1_Selecting">
            <SelectParameters>
                <asp:Parameter Name="p_rc" Direction="Output" />
            </SelectParameters>        

然后在代码后台,只需在命令对象中找到参数,并为其分配适当的类型

 protected void SqlDataSource1_Selecting
	(object sender, SqlDataSourceSelectingEventArgs e)
    {
        ((System.Data.OracleClient.OracleParameter)e.Command.Parameters[0]).OracleType =
             System.Data.OracleClient.OracleType.Cursor;
    }

创建自定义 Parameter 和 SqlDataSource

如果你想仅使用声明性语法来做到这一点,我提出了以下方法

首先,创建一个自定义 Parameter 控制,它将保存命令对象参数的属性名称(在我们的例子中为 OracleType),该属性名称设置参数类型,以及该属性的 enum 值(在我们的例子中为 Cursor)。

namespace CustomComponents
{
    public class DBSpecialParameter : Parameter
  {
    /// <summary>
    /// Gets or sets the string that contains the name of the property
    /// of the Parameter object which holds parameter type 
    /// </summary>
    
    public string DBParamTypePropertyName
    {
        get { return ViewState["DBParamTypePropertyName"] != 
            null ? (string)ViewState["DBParamTypePropertyName"] : string.Empty; }
        set { ViewState["DBParamTypePropertyName"] = value; }
    }
   /// <summary>
   /// The enum value  which has to be assigned to the DBParamTypePropertyName
   /// </summary>
    public string DBParamTypeEnumeValue
    {
        get { return ViewState["DBParamTypeEnumeValue"] != 
            null ? (string)ViewState["DBParamTypeEnumeValue"] : string.Empty; }
        set { ViewState["DBParamTypeEnumeValue"] = value; }
    }  
  }
}

接下来,我们对 SqlDataSource 进行子类化,以处理 Selecting 事件,使用反射找到适当的命令对象 Parameter,找到来自我们的 DBSpecialParameter.DBParamTypePropertyName 的属性名称,并将它的值设置为 DBSpecialParameter.DBParamTypeEnumeValue

这是执行此操作的代码

namespace CustomComponents
{
    /// <summary>
    /// Summary description for SqlDataSourceEx
    /// </summary>
    public class SqlDataSourceEx : System.Web.UI.WebControls.SqlDataSource
    {
        public SqlDataSourceEx()
        {
        }
        /// <summary>
        /// Attach a handler to Selecting event
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit(EventArgs e)
        {
            base.Selecting += 
               new System.Web.UI.WebControls.SqlDataSourceSelectingEventHandler(
               SqlDS_Selecting);
            base.OnInit(e);
        }
        /// <summary>
        /// Finds DBSpecialParameters in SqlDataSourceEx, find parameter in the
        /// Parameters collection of the command object with the same name, then using
        /// reflection find DBParamTypePropertyName property in the parameter and
        /// assign DBParamTypeEnumeValue to it.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="selectingArgs"></param>
        protected void SqlDS_Selecting(object sender,
            System.Web.UI.WebControls.SqlDataSourceSelectingEventArgs selectingArgs)
        {
            foreach (System.Web.UI.WebControls.Parameter selPar 
					in base.SelectParameters)
            {
                if (selPar is DBSpecialParameter)
                {
                    foreach (
                        System.Data.Common.DbParameter commParam 
					in selectingArgs.Command.Parameters)
                    {
                        if (selPar.Name == commParam.ParameterName)
                        {
                            try
                            {
                                // Cast to DBSpecialParameter
                                DBSpecialParameter dbp = selPar as DBSpecialParameter;
                                if (dbp == null)
                                    throw new ApplicationException(
                                    String.Format(
                                    "DBSpecialParameter error: {0} 
					is not DBSpecialParameter!",
                                    selPar.Name));
                                // Get parameter type object
                                Type t = commParam.GetType();
                                // Get the dbType property
                                PropertyInfo dbTypeProperty = t.GetProperty(
                                    dbp.DBParamTypePropertyName);
                                if (dbTypeProperty == null)
                                    throw new ApplicationException(String.Format(
                                    "DBSpecialParameter error: 
				No property with '{0}' name" +
                                    "exists in '{1}'!",
                                        dbp.DBParamTypePropertyName, t.FullName));
                                // Get type of the property 
                                Type enumType = dbTypeProperty.PropertyType;
                                // Get the cursor type enum value
                                FieldInfo evalue = enumType.GetField(
                                    dbp.DBParamTypeEnumeValue);
                                if (evalue == null)
                                    throw new ApplicationException(String.Format(
                                    "DBSpecialParameter error: 
				No enum value '{0}' exists" +
                                    "in '{1}'!",
                                       dbp.DBParamTypeEnumeValue, enumType.FullName));
                                // Set the dbType property to enum cursor value
                                dbTypeProperty.SetValue(commParam,
                                    evalue.GetValue(enumType), null);
                            }
                            catch
                            {
                                throw;
                            }
                            break;
                        }
                    }
                }
            }
        }
    }
}

这是我们可以用来从上述相同存储过程获取数据的声明性代码

<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSourceEx1">
</asp:GridView>
<custom:SqlDataSourceEx ID="SqlDataSourceEx1"  runat="server" 
            ConnectionString="<%$ ConnectionStrings:oraConnectionString %>" 
            ProviderName="<%$ ConnectionStrings:oraConnectionString.ProviderName %>" 
            SelectCommand="testCountries" SelectCommandType="StoredProcedure"  >
            <SelectParameters>             
             <custom:DBSpecialParameter Name="p_rc" Direction="Output"
                DBParamTypePropertyName="OracleType" DBParamTypeEnumeValue="Cursor" />
            </SelectParameters>    
</custom:SqlDataSourceEx>

编程愉快!

历史

  • 2009 年 1 月 5 日:初始发布
© . All rights reserved.