Skip to content

Instantly share code, notes, and snippets.

@JCKodel
Created March 31, 2016 02:32
Show Gist options
  • Save JCKodel/80ca7ed01355203b04f0c8a4a8a64d07 to your computer and use it in GitHub Desktop.
Save JCKodel/80ca7ed01355203b04f0c8a4a8a64d07 to your computer and use it in GitHub Desktop.
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Data" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
// ReSharper disable All
using System;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Threading.Tasks;
using SimpleInjector;
namespace <#= ns #>
{
#region Input
<#
var inputs = new Dictionary<string, List<string>>();
var outputs = new Dictionary<string, List<Tuple<string, string>>>();
using(var con = new SqlConnection(connectionString))
{
con.Open();
using(var cmd = new SqlCommand("SELECT SCHEMA_NAME(SCHEMA_ID) AS [Schema], SO.name AS [ObjectName], SO.Type_Desc AS [ObjectType (UDF/SP)], P.parameter_id AS [ParameterID], P.name AS [ParameterName], TYPE_NAME(P.user_type_id) AS [ParameterDataType], P.max_length AS [ParameterMaxBytes], P.is_output AS [IsOutPutParameter] FROM sys.objects AS SO INNER JOIN sys.parameters AS P ON SO.OBJECT_ID = P.OBJECT_ID WHERE SO.OBJECT_ID IN ( SELECT OBJECT_ID FROM sys.objects WHERE TYPE IN ('P','FN')) AND SCHEMA_NAME(SCHEMA_ID) = @SchemaName ORDER BY [Schema], SO.name, P.parameter_id", con))
{
cmd.Parameters.AddWithValue("@SchemaName", schemaFilter);
var procedureName = "";
using(var dr = cmd.ExecuteReader())
{
if(dr.HasRows)
{
while(dr.Read())
{
var objectName = (string)dr["ObjectName"];
var parameterName = ((string)dr["ParameterName"]).TrimStart('@');
var parameterType = (string)dr["ParameterDataType"];
var isOutputParameter = (bool)dr["IsOutPutParameter"];
if(FixName(objectName) != procedureName)
{
inputs[objectName] = new List<string>();
if(procedureName != "")
{
#>
}
<#
}
#>
/// <summary>
/// Argumentos de entrada para SP <#= objectName #>
/// </summary>
public partial class <#= FixName(objectName) #>Input
{
<#
procedureName = FixName(objectName);
}
if(isOutputParameter == false)
{
inputs[objectName].Add(parameterName);
#>
/// <summary>
/// Campo <#= parameterName #> de <#= objectName #>.
/// </summary>
public <#= SqlTypeToCSharpType(parameterType) #> <#= parameterName #> { get; set; }
<#
}
}
}
}
if(inputs.Count > 0)
{
#>
}
<# }
}
#>
#endregion
#region Output
<#
var procs = new List<string>();
using(var cmd = new SqlCommand("SELECT * FROM sys.procedures WHERE SCHEMA_NAME(schema_id) = @SchemaName", con))
{
cmd.Parameters.AddWithValue("@SchemaName", schemaFilter);
using(var dr = cmd.ExecuteReader())
{
while(dr.Read())
{
procs.Add((string)dr["name"]);
}
}
}
foreach(var objectName in procs)
{
using(var cmd = new SqlCommand("sp_describe_first_result_set", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@tsql", schemaFilter + "." + objectName);
using(var dr = cmd.ExecuteReader())
{
if(dr.HasRows)
{
outputs[objectName] = new List<Tuple<string, string>>();
#>
/// <summary>
/// Argumentos de saída para SP <#= objectName #>
/// </summary>
public partial class <#= FixName(objectName) #>Output
{
<#
while(dr.Read())
{
var outputName = FixName((string)dr["name"]);
var csharpType = SqlTypeToCSharpType((int)dr["system_type_id"], (bool)dr["is_nullable"]);
outputs[objectName].Add(new Tuple<string, string>(outputName, csharpType));
#>
/// <summary>
/// Campo <#= outputName #> de <#= objectName #>.
/// </summary>
public <#= csharpType #> <#= outputName #> { get; set; }
<#
}
#>
}
<#
}
}
}
}
#>
#endregion
#region Database client interface
/// <summary>
/// Dataclient para <#= databaseName #>.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1040:AvoidEmptyInterfaces")]
public interface I<#= databaseName #>
{
<#
foreach(var proc in procs)
{
#>
/// <summary>
/// Operação <#= proc #>.
/// </summary>
<#
if(outputs.ContainsKey(proc))
{#>Task<IList<<#= FixName(proc) #>Output>><#}
else
{#>Task<int><#}
#> <#= FixName(proc) #>Async(<#
if(inputs.ContainsKey(proc))
{
#><#= FixName(proc) #>Input args<#
}#>);
<# }
#>
}
#endregion
#region Database client implementation
internal sealed partial class <#= databaseName #> : BaseDataClient, I<#= databaseName #>
{
<#
foreach(var proc in procs)
{
#> public<#= outputs.ContainsKey(proc) ? " async " : " " #><#
if(outputs.ContainsKey(proc))
{#>Task<IList<<#= FixName(proc) #>Output>><#}
else
{#>Task<int><#}
#> <#= FixName(proc) #>Async(<#
if(inputs.ContainsKey(proc))
{
#><#= FixName(proc) #>Input args<#
}#>)
{
<#
if(inputs.ContainsKey(proc))
{
#>
var pars = new List<SqlParameter>
{
<#
foreach(var arg in inputs[proc])
{#>
new SqlParameter("@<#= arg #>", NullConverter(args.<#= arg #>)),
<#
}
#>
};
<#
}
if(outputs.ContainsKey(proc))
{#>
var result = new List<<#= FixName(proc) #>Output>();
await ExecuteAsync("<#= schemaFilter + "." + proc #>"<#= inputs.ContainsKey(proc) ? ", pars" : ""#>, dr =>
{
result.Add(new <#= FixName(proc) #>Output
{
<#foreach(var arg in outputs[proc])
{#>
<#= arg.Item1 #> = GetSafeValue<<#= arg.Item2 #>>(dr["<#= arg.Item1 #>"]),
<#}#>
});
});
return result;
<#
}
else
{
#>
return ExecuteNonQueryAsync("<#= schemaFilter + "." + proc #>"<#= inputs.ContainsKey(proc) ? ", pars" : ""#>);
<#
}
#>
}
<# }
#>
}
#endregion
#region IoC Registration
internal static class ModelGenerator
{
public static void ConfigureIoC(Container container)
{
container.Register<I<#= databaseName #>, <#= databaseName #>>(Lifestyle.Scoped);
}
}
#endregion
}
<#
}
#>
<#+
string FixName(string name)
{
if(string.IsNullOrEmpty(name))
{
return name;
}
name = name.Replace("_tb", "");
name = name.Replace("_sps", "");
name = name.Replace("_spi", "");
name = name.Replace("_spu", "");
name = name.Replace("_spd", "");
name = name.Substring(0, 1).ToUpper() + name.Substring(1);
while(true)
{
var index = name.IndexOf("_");
if(index == -1)
{
break;
}
name = name.Substring(0, index) + name.Substring(index + 1, 1).ToUpper() + name.Substring(index + 2);
}
return name;
}
string SqlTypeToCSharpType(int sqlType, bool isNullable)
{
var nullable = isNullable ? "?" : "";
switch(sqlType)
{
case 35:
case 167:
case 175:
return "string";
case 36:
return "Guid" + nullable;
case 40:
case 41:
case 42:
case 43:
case 58:
return "DateTime" + nullable;
case 48:
return "byte" + nullable;
case 52:
return "short" + nullable;
case 56:
return "int" + nullable;
case 59:
return "single" + nullable;
case 60:
case 106:
return "decimal" + nullable;
case 62:
return "float" + nullable;
case 104:
return "bool" + nullable;
case 127:
return "long" + nullable;
case 165: // varbinary
return "byte[]";
default:
throw new NotImplementedException("Tipo SQL " + sqlType + " não implementado");
}
}
string SqlTypeToCSharpType(string sqlType)
{
var type = sqlType.ToLower();
if(type.Contains("("))
{
type = type.Substring(0, type.IndexOf("("));
}
switch(type)
{
case "char":
case "text":
case "varchar":
return "string";
case "uniqueidentifier":
return "Guid?";
case "date":
case "time":
case "datetime":
return "DateTime?";
case "datetime2":
case "datetimeoffset":
case "smalldatetime":
return "DateTime?";
case "tinyint":
return "byte?";
case "smallint":
return "short?";
case "int":
return "int?";
case "real":
return "single?";
case "money":
case "decimal":
return "decimal?";
case "float":
return "float?";
case "bit":
return "bool?";
case "bigint":
return "long?";
case "varbinary":
return "byte[]";
default:
throw new NotImplementedException("Tipo SQL " + sqlType + " não implementado");
}
}
#>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment