【问题标题】:How to return a strongly-typed object from a SubSonic SPROC call with SPROC parameters?如何从带有 SPROC 参数的 SubSonic SPROC 调用中返回强类型对象?
【发布时间】:2011-05-31 22:16:26
【问题描述】:

我有一个数据调用方法,它返回一个 ItemDatumCollection 类型的 SubSonic 集合。

sproc 执行如下:

itemDatumCollection.LoadAndCloseReader(sp.GetReader());

但是,我无法以这种方式访问​​存储过程的输出参数,因为我可以在调用 sp.GetDataSet() 时执行以下操作:

            itemsDataSet = sp.GetDataSet();

            actualNumberOfResults = ((Int64)sp.OutputValues[1]);
            numberOfResultsReturned = ((Int64)sp.OutputValues[2]);

有没有办法使用第一种方法访问存储过程的输出参数 - 从我的存储过程调用返回一个 SubSonic 强类型集合?

谢谢。

【问题讨论】:

    标签: c# sql-server-2008 stored-procedures subsonic strongly-typed-dataset


    【解决方案1】:

    我想做类似的事情,并最终更改了大部分 StoredProcedures.tt 文件,我认为是 SubSonic 的一些内部结构。没有太详细,我通过 .tt 文件进行了更改,以便它会为给定的存储过程生成这个:

        public void COMPANIES_ACTIVATE_PACKAGE(long PI_COMPANY_ID, string PI_ACTIVE, long PI_USER_ID, out long PO_ERRCODE, out string PO_ERRMSG, out string PO_ORA_ERRMSG){
            StoredProcedure sp=new StoredProcedure("COMPANIES.ACTIVATE_PACKAGE",this.Provider);
            sp.Command.AddParameter("PI_COMPANY_ID",PI_COMPANY_ID,DbType.Decimal);
            sp.Command.AddParameter("PI_ACTIVE",PI_ACTIVE,DbType.AnsiString);
            sp.Command.AddParameter("PI_USER_ID",PI_USER_ID,DbType.Decimal);
            sp.Command.AddOutputParameter("PO_ERRCODE",DbType.AnsiString);
            sp.Command.AddOutputParameter("PO_ERRMSG",DbType.AnsiString);
            sp.Command.AddOutputParameter("PO_ORA_ERRMSG",DbType.AnsiString);
            sp.Execute();
            var prms = sp.Command.Parameters;
            PO_ERRCODE = ConvertValue<long>(prms.GetParameter("PO_ERRCODE").ParameterValue);
            PO_ERRMSG = ConvertValue<string>(prms.GetParameter("PO_ERRMSG").ParameterValue);
            PO_ORA_ERRMSG = ConvertValue<string>(prms.GetParameter("PO_ORA_ERRMSG").ParameterValue);
        }
    

    所以基本上我传入任何 sproc 参数,并为返回值定义了“out”参数。

    这里也没有显示,但如果我有一个 InOut 参数,那么我通过 ref 而不是 out 传递它。

    然后在我的实际应用程序代码中,我可以像调用任何其他函数一样调用存储过程:

    long errorCode;
    string errorMsg, oraErrorMsg;
    
    db.COMPANIES_ACTIVATE_PACKAGE(123, "Y", 456, out errorCode, out errorMsg, out oraErrorMsg);
    
    if(errorCode > 0)
        // ... handle error...
    

    我不知道这是否会直接插入 SS 而无需进一步更改,但这是我的 .tt 文件。您也许可以使用它,或者至少知道该去哪里:

    StoredProcedures.tt

    <#@ template language="C#" debug="False" hostspecific="True"  #>
    <#@ output extension=".cs" #>
    <#@ include file="DB2DataProvider.ttinclude" #>
    <#
        var sps = GetSPs(); 
        if(sps.Count>0){ 
    #>  
    using System;
    using System.Data;
    using System.ComponentModel;
    using SubSonic;
    using SubSonic.Schema;
    using SubSonic.DataProviders;
    
    namespace <#=Namespace#>{
        public partial class <#=DatabaseName#>DB{
    
            public T ConvertValue<T>(object paramVal)
            {
                if (paramVal == null || Convert.IsDBNull(paramVal))  // if the value is null, return the default for the desired type.
                    return default(T);
                if (typeof(T) == paramVal.GetType())  // if types are already equal, no conversion needed. just cast.
                    return (T)paramVal;
                else // types don't match. try to convert.
                {
                    var conversionType = typeof(T);
                    if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
                    {
                        NullableConverter nullableConverter = new NullableConverter(conversionType);
                        conversionType = nullableConverter.UnderlyingType;
                    }
                    return (T)Convert.ChangeType(paramVal, conversionType);
                }
            }
    
    <#  foreach(var sp in sps){#>
            public void <#=sp.CleanName#>(<#=sp.ArgList#>){
                StoredProcedure sp=new StoredProcedure("<#=sp.Name#>",this.Provider);
    <#      foreach(var par in sp.Parameters) {
              if(par.In && !par.Out) {#>
                sp.Command.AddParameter("<#=par.Name#>",<#=par.CleanName#>,DbType.<#=par.DbType#>);
    <#        } else if(!par.In && par.Out) {#>
                sp.Command.AddOutputParameter("<#=par.Name#>",DbType.<#=par.DbType#>);
    <#        } else {#>
                sp.Command.AddParameter("<#=par.Name#>",<#=par.CleanName#>,DbType.<#=par.DbType#>,ParameterDirection.InputOutput);
    <#      }}#>
                sp.Execute();
    <#      bool hasOut = false;
            foreach(var par in sp.Parameters) {
              if(par.Out)
                hasOut = true;
            }
            if(hasOut) {
    #>
                var prms = sp.Command.Parameters;
    <#      }
            foreach(var par in sp.Parameters) {
              if(par.Out) {#>
                <#=par.Name#> = ConvertValue<<#=par.SysType#>>(prms.GetParameter("<#=par.Name#>").ParameterValue);
    <#      }}#>
            }
    <#  }#>
    
        }
    
    }
    <#  }#>
    

    我很确定我还必须更改在数据库提供程序 .ttinclude 文件中加载存储过程数据的查询,以加载指示它是 In、Out 还是 InOut 参数类型的列。

    ...希望这对您有所帮助...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多