Как вернуть строго типизированный объект из вызова SubSonic SPROC с параметрами SPROC? - PullRequest
0 голосов
/ 01 июня 2011

У меня есть метод вызова данных, который возвращает коллекцию SubSonic типа ItemDatumCollection.

Выполнение sproc выполняется следующим образом:

itemDatumCollection.LoadAndCloseReader(sp.GetReader());

Однако я не могу получить доступ к выходным параметрамsproc таким образом, что я могу сделать при вызове sp.GetDataSet () следующим образом:

            itemsDataSet = sp.GetDataSet();

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

Есть ли способ получить доступ к выходным параметрам sproc с помощью первого метода - возврата SubSonicстрого типизированная коллекция из моего звонка?

Спасибо.

1 Ответ

0 голосов
/ 03 июня 2011

Я хотел сделать что-то подобное и закончил тем, что изменил большую часть файла 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.

... Надеюсь, это поможет ...

...