2 votes

Subsonic 3.0 manque le support des paramètres de sortie/par défaut dans SQL Server ?

J'ai une procédure stockée :

CREATE PROCEDURE MyProc ( @P1 uniqueidentifier, @P2 int = NULL output, @P3 int = NULL output )

La signature du côté C# devrait être (Guid P1, int ? P2, int ? P3) je pense. Mais ce n'est pas le cas, c'est juste (Guid,int,int). De plus, les paramètres de sortie ne sont pas créés en tant que paramètres de sortie, ils sont juste des "AddParameter(P2,arg,DbType.Int32)". Est-ce que cela devait fonctionner ?

2voto

Max Metral Points 31

Eh bien, il ne semble pas que les modèles natifs de T4 gèrent cela si bien. Nous avions en fait construit quelque chose de plus complexe à l'époque de VS2003, et je l'ai donc mis à jour pour Subsonic. L'idée était que chaque proc stocké obtienne une classe au lieu d'une fonction et ait des propriétés nullables pour les paramètres. J'ai modifié plusieurs modèles, je suis sûr qu'il me manque quelque chose ici et ce n'est pas "qualité production", mais voici StoredProcedures.tt

<#@ template language="C#v3.5" debug="False" hostspecific="True"  #>
<#@ output extension=".cs" #>
<#@ include file="SQLServer.ttinclude" #>
<#
    var sps = GetSPs(); 
    if(sps.Count>0){ 
#>  
using System;
using SubSonic;
using SubSonic.Schema;
using SubSonic.DataProviders;
using System.Data;

namespace <#=Namespace#>{
    public partial class <#=DatabaseName#>DB{

<#  foreach(var sp in sps){#>
        public class <#=sp.CleanName#> : StoredProcedure
        {
            public <#=sp.CleanName#>(<#=DatabaseName#>DB database, <#=sp.ArgList#>) : base("<#=sp.Name#>",database.Provider)
            {
<#      foreach(var par in sp.Parameters){
            if (par.IsOutput) { #>
                Command.AddOutputParameter("<#=par.Name#>",DbType.<#=par.DbType#>);
<#
            }
            else
            {
#>
                Command.AddParameter("<#=par.Name#>",<#=par.CleanName#>,DbType.<#=par.DbType#>);
<#      
            }
        }#>
            }

<#  foreach (var par in sp.Parameters) { #>
            public <#= par.SysType #><#= par.ShouldBeNullable ? "?" : "" #> <#= par.CleanName #>
            {
                get
                {
                    object val = Command.Parameters.GetParameter("<#= par.Name #>").ParameterValue;
                    return val == DBNull.Value ? default(<#= par.SysType #><#= par.ShouldBeNullable ? "?" : "" #>) : (<#= par.SysType #><#= par.ShouldBeNullable ? "?" : "" #>)val;
                }
                set             
                {
<#          if (par.ShouldBeNullable) { #>
                    object val = value.HasValue ? (object)value : (object)DBNull.Value;
                    Command.Parameters.GetParameter("<#= par.Name #>").ParameterValue = val;
<#          } #>
                }
            }
<#  }   #>
        }

<#  } #>
    }

}
<#  }#> 

Et voici la fonction GetSPParams de SQLServer.ttinclude

List<SPParam> GetSPParams(string spName){
    var result=new List<SPParam>();
    string[] restrictions = new string[4] { DatabaseName, null, spName, null };
    using(SqlConnection conn=new SqlConnection(ConnectionString)){
        conn.Open();
        var sprocs=conn.GetSchema("ProcedureParameters", restrictions);
        conn.Close();
        foreach(DataRow row in sprocs.Select("", "ORDINAL_POSITION")){
            SPParam p=new SPParam();
            p.SysType=GetSysType(row["DATA_TYPE"].ToString());
            p.DbType=GetDbType(row["DATA_TYPE"].ToString()).ToString();
            p.Name=row["PARAMETER_NAME"].ToString().Replace("@","");
            p.IsOutput=(row["PARAMETER_MODE"].ToString() == "INOUT");
            p.CleanName=CleanUp(p.Name);
            result.Add(p);
        }

    }
    return result;
}

Et ensuite la déclaration de classe de Settings.ttinclude

public class SP{
    public string Name;
    public string CleanName;
    public string ClassName;
    public List<SPParam> Parameters;
    public SP(){
        Parameters=new List<SPParam>();
    }        
    public string ArgList{
        get{
            StringBuilder sb=new StringBuilder();
            foreach(var par in Parameters){
                    if (par.ShouldBeNullable) { continue; }
                if(sb.Length != 0)
                {
                    sb.Append(", ");
                }
                sb.AppendFormat("{0}{1} {2}", par.SysType, par.ShouldBeNullable ? "?" : "", par.CleanName);
            }
            return sb.ToString();
        }
    }
}
public class SPParam{
    public string Name;
    public string CleanName;
    public string SysType;
    public string DbType;
    public bool IsOutput;
    public bool ShouldBeNullable
    {
     get
     {
            return IsOutput && (SysType == "int" || SysType == "bool" || SysType == "double" || SysType == "long" || SysType == "short" || SysType == "decimal");
     }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X