Created
March 31, 2016 02:32
-
-
Save JCKodel/80ca7ed01355203b04f0c8a4a8a64d07 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<#@ 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