public void DTOObjectSingleSelectMultipleRowMultipleColumnTest()
        {
            // Arrange
            var helper = new ProcedureHelper();
            var procedure = new Procedure("proc", "proc", null, null, new List<Select>{
                new Select(new List<SelectColumn>{
                    new SelectColumn("col1", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Int32?"), true),
                    new SelectColumn("col2", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "String"), true)
                }, false, null)
            });

            // Act
            var result = helper.GetDtoObject(procedure);

            // Assert
            Assert.AreEqual(@"/// <summary>
            /// DTO for the output of the ""proc"" stored procedure.
            /// </summary>
            public partial class procOutputDto
            {
            public Int32? col1 { get; set; }
            public String col2 { get; set; }
            }

            ", result);
        }
        public void DTOObjectNoSelectTest()
        {
            // Arrange
            var helper = new ProcedureHelper();
            var procedure = new Procedure("proc", "proc", null, null, null);

            // Act
            var result = helper.GetDtoObject(procedure);

            // Assert
            Assert.AreEqual("", result);
        }
        public void DTOObjectSingleSelectMultipleRowSingleColumnTest()
        {
            // Arrange
            var helper = new ProcedureHelper();
            var procedure = new Procedure("proc", "proc", null, null, new List<Select>{
                new Select(new List<SelectColumn>{
                    new SelectColumn("col1", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Int32?"), true)
                }, false, null)
            });

            // Act
            var result = helper.GetDtoObject(procedure);

            // Assert
            Assert.AreEqual("", result);
        }
        /// <summary>
        /// Gets the parameter list for the method.
        /// </summary>
        /// <param name="proc">The procedure to get the parameter list for.</param>
        /// <param name="genericTableValue">if set to <c>true</c> [generic table value].</param>
        /// <param name="includeType">if set to <c>true</c> [include type].</param>
        /// <param name="convertType">if set to <c>true</c> [convert type].</param>
        /// <returns>
        /// The generated parameter list.
        /// </returns>
        public string GetMethodParamList(Procedure proc, bool genericTableValue, bool includeType, bool convertType)
        {
            var b = new TextBuilder();
            for (var i = 0; i < proc.Parameters.Count(); i++)
            {
                var parameter = proc.Parameters.ElementAt(i);
                if (i != 0) b.Append(", ");
                if (parameter.IsTableValue)
                {
                    if (includeType)
                    {
                        if (genericTableValue)
                        {
                            var format = convertType ? "(IEnumerable<ITableValuedParamRow>){0}" : "IEnumerable<ITableValuedParamRow> {0}";
                            b.AppendFormat(format, parameter.Name);
                        }
                        else
                        {
                            var format = convertType ? "(IEnumerable<{0}_{1}ParamDto>){1}" : "IEnumerable<{0}_{1}ParamDto> {1}";
                            b.AppendFormat(format, proc.Name, parameter.Name);
                        }
                    }
                    else b.Append(parameter.Name);
                }
                else
                {
                    if (parameter.IsOutput) b.Append("out ");

                    if (includeType)
                    {
                        var format = convertType ? "({0}){1}" : "{0} {1}";
                        b.AppendFormat(format, parameter.DataTypes[TypeFormat.DotNetFrameworkType], parameter.Name);
                    }
                    else b.Append(parameter.Name);
                }
            }
            return b.ToString();
        }
        /// <summary>
        /// Gets the DTO return objects that represent a row of each result set of each procedure.
        /// </summary>
        /// <param name="proc">The procedure to generate the DTO from.</param>
        /// <param name="indent">The number of tabs to indent the generated code.</param>
        /// <returns>
        /// The generated DTO objects.
        /// </returns>
        public string GetDtoObject(Procedure proc, int indent = 0)
        {
            var b = new TextBuilder();
            b.Indent(indent);

            if (proc.Parameters.Any())
            {
                // Create the input DTO.
                b.AppendLine("/// <summary>");
                b.AppendFormatLine("/// DTO for the input of the \"{0}\" stored procedure.", proc.RawName);
                b.AppendLine("/// </summary>");
                b.AppendFormatLine("public partial class {0}InputDto", proc.Name);
                b.AppendLine("{");
                b.Indent();
                foreach (var p in proc.Parameters)
                {
                    b.AppendLine("/// <summary>");
                    b.AppendFormatLine(p.IsOutput ?
                        "/// Property that gets filled with the {0} output parameter." :
                        "/// Property that fills the {0} input parameter.", p.Name);
                    b.AppendLine("/// </summary>");
                    if (p.IsTableValue)
                    {
                        b.AppendFormatLine("public IEnumerable<{0}_{1}ParamDto> {1} {{ get; set; }}", proc.Name, p.Name);
                    }
                    else
                    {
                        var cSharpType = p.DataTypes[TypeFormat.DotNetFrameworkType];
                        b.AppendFormatLine("public {0} {1} {{ get; {2}set; }}", cSharpType, p.Name, p.IsOutput ? "internal " : "");
                    }

                }
                b.Unindent();
                b.AppendLine("}");
                b.AppendLine();

                // Create DTOs for any table-valued parameters.
                foreach (var p in proc.Parameters.Where(x => x.IsTableValue))
                {
                    b.AppendLine("/// <summary>");
                    b.AppendFormatLine("/// DTO for the input of the \"{0}\" table-valued parameter of the \"{1}\" stored procedure.", p.Name, proc.RawName);
                    b.AppendLine("/// </summary>");
                    b.AppendFormatLine("public partial class {0}_{1}ParamDto : ITableValuedParamRow", proc.Name, p.Name);
                    b.AppendLine("{");
                    b.Indent();
                    foreach (var c in p.TableValue.Columns)
                    {
                        var cSharpType = c.DataTypes[TypeFormat.DotNetFrameworkType];
                        if (!c.IsNullable) cSharpType = cSharpType.TrimEnd('?');
                        b.AppendFormatLine("public {0} {1} {{ get; set; }}", cSharpType, c.Name);
                    }
                    b.AppendLine();
                    b.AppendLine("public SqlDataRecord ToSqlDataRecord()");
                    b.AppendLine("{");
                    b.Indent();
                    b.AppendLine("var sdr = new SqlDataRecord(");
                    b.Indent();
                    for (var i = 0; i < p.TableValue.Columns.Count(); i++)
                    {
                        var c = p.TableValue.Columns.ElementAt(i);
                        var comma = i == p.TableValue.Columns.Count() - 1 ? "" : ",";
                        b.AppendFormatLine("new SqlMetaData(\"{0}\", SqlDbType.{1}){2}", c.Name, c.DataTypes[TypeFormat.SqlDbTypeEnum], comma);
                    }
                    b.Unindent();
                    b.AppendLine(");");
                    for (var i = 0; i < p.TableValue.Columns.Count(); i++)
                    {
                        var c = p.TableValue.Columns.ElementAt(i);
                        var setFn = "Set" + c.DataTypes[TypeFormat.SqlDataReaderDbType].Substring(3);
                        if (c.IsNullable && c.DataTypes[TypeFormat.DotNetFrameworkType].EndsWith("?"))
                            b.AppendFormatLine("if({2}.HasValue) sdr.{0}({1}, {2}.GetValueOrDefault()); else sdr.SetDBNull({1});", setFn, i.ToString(), c.Name);
                        else
                            b.AppendFormatLine("sdr.{0}({1}, {2});", setFn, i.ToString(), c.Name);
                    }
                    b.AppendLine("return sdr;");
                    b.Unindent();
                    b.AppendLine("}");
                    b.Unindent();
                    b.AppendLine("}");
                    b.AppendLine();
                }
            }

            // If only one select and one column, no output DTO is needed.
            if (proc.Selects.Count() == 1 && proc.Selects.First().Columns.Count() == 1)
                return b.ToString();

            // Create output DTOs.
            for (var i = 0; i < proc.Selects.Count(); i++)
            {
                b.AppendLine("/// <summary>");
                b.AppendFormatLine("/// DTO for the output of the \"{0}\" stored procedure.", proc.RawName);
                b.AppendLine("/// </summary>");
                b.AppendFormat("public partial class {0}OutputDto", proc.Name);
                if (i > 0) b.StringBuilder.Append((i + 1).ToString());
                b.AppendLine();
                b.AppendLine("{");
                b.Indent();
                foreach (var col in proc.Selects.ElementAt(i).Columns)
                {
                    var cSharpType = col.DataTypes[TypeFormat.DotNetFrameworkType];
                    if (!col.IsNullable) cSharpType = cSharpType.TrimEnd('?');
                    b.AppendFormatLine("public {0} {1} {{ get; set; }}", cSharpType, col.Name);
                }
                b.Unindent();
                b.AppendLine("}");
                b.AppendLine();
            }

            // If multiple selects, create an object to hold all the results.
            if (proc.Selects.Count() > 1)
            {
                b.AppendFormatLine("public partial class {0}Results", proc.Name);
                b.AppendLine("{");
                b.Indent();
                b.AppendLine("public int RecordsAffected { get; set; }");
                for (var i = 0; i < proc.Selects.Count(); i++)
                {
                    var inc = i > 0 ? (i + 1).ToString() : "";
                    b.AppendFormatLine("public IEnumerable<{0}OutputDto{1}> Result{1} {{ get; set; }}", proc.Name, inc);
                }
                b.Unindent();
                b.AppendLine("}");
                b.AppendLine();
            }
            b.Unindent();
            return b.ToString();
        }
        /// <summary>
        /// Gets the generated statement that executes the stored procedure and loads the results
        /// into the return variable.
        /// </summary>
        /// <param name="proc">The procedure to get the generated execute statement for.</param>
        /// <param name="indent">The number of tabs to indent the generated code.</param>
        /// <returns>
        /// The generated code.
        /// </returns>
        public string GetExecuteStatement(Procedure proc, int indent = 0)
        {
            var b = new TextBuilder();
            b.Indent(indent);

            var singleSelect = proc.Selects.Count() == 1;
            var singleSelectRow = singleSelect && proc.Selects.First().IsSingleRow;
            var singleColumn = singleSelect && proc.Selects.First().Columns.Count() == 1;
            var singleValue = singleSelectRow && singleColumn;

            // If no SELECT statements, use ExecuteNonQuery().
            if (!proc.Selects.Any())
            {
                b.AppendLine("result = cmd.ExecuteNonQuery();");
            }
            // If only one SELECT statement with one column that returns one value, use ExecuteScalar().
            else if (singleValue)
            {
                var col = proc.Selects.First().Columns.First();
                var cSharpType = col.DataTypes[TypeFormat.DotNetFrameworkType];
                if (!col.IsNullable) cSharpType = cSharpType.TrimEnd('?');
                b.AppendFormatLine("result = ({0})cmd.ExecuteScalar();", cSharpType);
            }
            else
            {
                b.AppendLine("using(var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))");
                b.AppendLine("{");
                b.Indent();
                b.AppendLine("result.RecordsAffected = reader.RecordsAffected;");
                for (var i = 0; i < proc.Selects.Count(); i++)
                {
                    var inc = i > 0 ? (i + 1).ToString() : "";
                    var select = proc.Selects.ElementAt(i);

                    // If multiple selects OR muliple rows, declare a list for this select's results.
                    if (proc.Selects.Count() > 1 || !select.IsSingleRow)
                    {
                        // If only one select with one column, use a primitive list, else use a DTO list.
                        if (singleColumn)
                        {
                            var col = select.Columns.First();
                            var cSharpType = col.DataTypes[TypeFormat.DotNetFrameworkType];
                            if (!col.IsNullable) cSharpType = cSharpType.TrimEnd('?');
                            b.AppendFormatLine("var list = new List<{0}>();", cSharpType);
                        }
                        else b.AppendFormatLine("var list{1} = new List<{0}OutputDto{1}>();", proc.Name, inc);
                    }

                    // Start reading the records.
                    b.AppendLine("while (reader.Read())");
                    b.AppendLine("{");
                    b.Indent();
                    // If only one select with one column, use a primitive, else use a DTO.
                    if (singleColumn)
                    {
                        var col = select.Columns.First();
                        var cSharpType = col.DataTypes[TypeFormat.DotNetFrameworkType];
                        if (!col.IsNullable) cSharpType = cSharpType.TrimEnd('?');
                        b.AppendFormatLine("{0} item;", cSharpType);
                    }
                    else
                        b.AppendFormatLine("var item = new {0}OutputDto{1}();", proc.Name, inc);

                    for (var j = 0; j < select.Columns.Count(); j++)
                    {
                        // If datatype is binary, use the GetBytes helper function.
                        var col = select.Columns.ElementAt(j);
                        if (col.DataTypes[TypeFormat.SqlDataReaderDbType] == "GetBytes")
                        {
                            if (singleColumn) b.AppendFormatLine("item = GetBytes(reader, {0});", j.ToString());
                            else b.AppendFormatLine("item.{0} = GetBytes(reader, {1});", col.Name, j.ToString());
                        }
                        else
                        {
                            if (col.IsNullable)
                            {
                                if (singleColumn) b.AppendFormatLine("item = !reader.IsDBNull({1}) ? reader.{0}({1}) : default({2});", col.DataTypes[TypeFormat.SqlDataReaderDbType], j.ToString(), col.DataTypes[TypeFormat.DotNetFrameworkType]);
                                else b.AppendFormatLine("item.{0} = !reader.IsDBNull({2}) ? reader.{1}({2}) : default({3});", col.Name, col.DataTypes[TypeFormat.SqlDataReaderDbType], j.ToString(), col.DataTypes[TypeFormat.DotNetFrameworkType]);
                            }
                            else
                            {
                                if (singleColumn) b.AppendFormatLine("item = reader.{0}({1});", col.DataTypes[TypeFormat.SqlDataReaderDbType], j.ToString());
                                else b.AppendFormatLine("item.{0} = reader.{1}({2});", col.Name, col.DataTypes[TypeFormat.SqlDataReaderDbType], j.ToString());
                            }
                        }
                    }

                    // If selecting a single row, assign directly to result, else add to list of results.
                    if (singleSelectRow) b.AppendLine("result.Data = item;");
                    else b.AppendFormatLine("list{0}.Add(item);", inc);

                    b.Unindent();
                    b.AppendLine("}");

                    // If only one select statement
                    if (singleSelect)
                    {
                        // If not returning a single row, return the list,
                        // else the item should have already been assigned directly to the result above.
                        if (!select.IsSingleRow) b.AppendLine("result.Data = list;");
                    }
                    else // If multiple selects, assign the result and move to the next one.
                    {
                        b.AppendFormatLine("result.Result{0} = list{0};", inc);
                        b.AppendLine("reader.NextResult();");
                    }
                }
                b.AppendLine("reader.Close();");
                b.Unindent();
                b.AppendLine("}");
            }

            // Assign values for any output parameters.
            foreach (var outputParameter in proc.Parameters.Where(x => x.IsOutput))
            {
                b.AppendFormatLine("{0} = {0}OutputParameter.Value as {1};", outputParameter.Name, outputParameter.DataTypes[TypeFormat.DotNetFrameworkType]);
            }
            return b.ToString();
        }
        public void ExecuteStatementNoSelectTest()
        {
            // Arrange
            var helper = new ProcedureHelper();
            var procedure = new Procedure("proc", "proc", null, null, null);

            // Act
            var result = helper.GetExecuteStatement(procedure);

            // Assert
            Assert.AreEqual("result = cmd.ExecuteNonQuery();\r\n", result);
        }
        /// <summary>
        /// Gets the Xml comment to place in the &lt;returns%gt; element.
        /// </summary>
        /// <param name="proc">The procedure to get the return variable declaration statement.</param>
        /// <returns>
        /// The Xml comment
        /// </returns>
        public string GetReturnXmlComment(Procedure proc)
        {
            var multiSelect = proc.Selects.Count() > 1;
            var singleSelect = proc.Selects.Count() == 1;
            var singleColumn = singleSelect && proc.Selects.First().Columns.Count() == 1;
            var isSingleRow = singleSelect && proc.Selects.First().IsSingleRow;

            if (singleColumn) return (isSingleRow ? "The value of " : "An IEnumerable of ") + proc.Selects.First().Columns.First().Name;
            if (singleSelect) return (isSingleRow ? "A DTO " : "An IEnumerable of DTOs ") + "filled with the results of the SELECT statement.";
            if (multiSelect) return "An object containing all the SELECT results in properties named 'Result', 'Result2', 'Result3', etc.";
            return "The number of rows affected.";
        }
 /// <summary>
 /// Gets the type of object the procedure's function will return.
 /// </summary>
 /// <param name="proc">The procedure to get the return type for.</param>
 /// <returns>
 /// The generated return type.
 /// </returns>
 public string GetReturnType(Procedure proc)
 {
     if (proc.Selects.Count() > 1)
         return proc.Name + "Results";
     else if (proc.Selects.Count() == 1)
     {
         var select = proc.Selects.First();
         if (select.Columns.Count() == 1)
         {
             var col = select.Columns.First();
             var cSharpType = col.DataTypes[TypeFormat.DotNetFrameworkType];
             if (!col.IsNullable) cSharpType = cSharpType.TrimEnd('?');
             return select.IsSingleRow ? cSharpType : "Result<IEnumerable<" + cSharpType + ">>";
         }
         else
         {
             return string.Format(select.IsSingleRow ? "Result<{0}>" : "Result<IEnumerable<{0}>>", proc.Name + "OutputDto");
         }
     }
     else
     {
         return "int";
     }
 }
        public void ReturnTypeMultipleSelectTest()
        {
            // Arrange
            var helper = new ProcedureHelper();
            var procedure = new Procedure("proc", "proc", null, null, new List<Select>{
                new Select(new List<SelectColumn>{
                  new SelectColumn("col1", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Int32?"), true),
                  new SelectColumn("col2", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "String"), true)
                }, false, null),
                new Select(new List<SelectColumn>{
                  new SelectColumn("col1", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Int32?"), true),
                  new SelectColumn("col2", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "String"), true)
                }, true, null)
            });

            // Act
            var result = helper.GetReturnType(procedure);

            // Assert
            Assert.AreEqual("procResults", result);
        }
        public void ReturnTypeMultipleRowSingleColumnTest()
        {
            // Arrange
            var helper = new ProcedureHelper();
            var procedure = new Procedure("proc", "proc", null, null, new List<Select>{
                new Select(new List<SelectColumn>{
                  new SelectColumn("col1", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Int32?"), false)
                }, false, null)
            });

            // Act
            var result = helper.GetReturnType(procedure);

            // Assert
            Assert.AreEqual("Result<IEnumerable<Int32>>", result);
        }
        public void MethodParameterTest()
        {
            // Arrange
            var helper = new ProcedureHelper();
            var procedure = new Procedure("proc", "proc", null, new List<Parameter> {
                new Parameter("param1", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Int32?"), false, null),
                new Parameter("param2", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Int32?"), true, null)
            }, null);

            // Act
            var result = helper.GetMethodParamList(procedure, true, true, false);

            // Assert
            Assert.AreEqual("Int32? param1, out Int32? param2", result);
        }
        public void ExecuteStatementSingleValueTest()
        {
            // Arrange
            var helper = new ProcedureHelper();
            var procedure = new Procedure("proc", "proc", null, null, new List<Select>{
                new Select(new List<SelectColumn>{
                    new SelectColumn("col1", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Int32?"), false)
                }, true, null)
            });

            // Act
            var result = helper.GetExecuteStatement(procedure);

            // Assert
            Assert.AreEqual("result = (Int32)cmd.ExecuteScalar();\r\n", result);
        }
        public void ExecuteStatementSingleRowMulipleColumnTest()
        {
            // Arrange
            var helper = new ProcedureHelper();
            var procedure = new Procedure("proc", "proc", null, null, new List<Select>{
                new Select(new List<SelectColumn>{
                    new SelectColumn("col1", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Int32?"), true),
                    new SelectColumn("col2", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "String"), true),
                }, true, null)
            });

            // Act
            var result = helper.GetExecuteStatement(procedure);

            // Assert
            Assert.AreEqual(@"using(var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
            {
            result.RecordsAffected = reader.RecordsAffected;
            while (reader.Read())
            {
            var item = new procOutputDto();
            item.col1 = !reader.IsDBNull(0) ? reader.GetInt32(0) : default(Int32?);
            item.col2 = !reader.IsDBNull(1) ? reader.GetString(1) : default(String);
            result.Data = item;
            }
            reader.Close();
            }
            ", result);
        }
 /// <summary>
 /// Gets the method parameter list for methods that call an overload
 /// with input DTO properties as parameters.
 /// </summary>
 /// <param name="proc">The proc.</param>
 /// <returns></returns>
 public string GetMethodParamListForInputDto(Procedure proc)
 {
     var b = new TextBuilder();
     for (var i = 0; i < proc.Parameters.Count(); i++)
     {
         var parameter = proc.Parameters.ElementAt(i);
         if (i != 0) b.Append(", ");
         b.AppendFormat(parameter.IsOutput ? "out {0}Output" : "input.{0}", parameter.Name);
     }
     return b.ToString();
 }
        /// <summary>
        /// Gets the method parameter list for object array.
        /// </summary>
        /// <param name="proc">The proc.</param>
        /// <returns></returns>
        public string GetMethodParamListForObjectArray(Procedure proc)
        {
            var b = new TextBuilder();
            var objectIndex = 0;
            for (var i = 0; i < proc.Parameters.Count(); i++)
            {
                var parameter = proc.Parameters.ElementAt(i);
                if (i != 0) b.Append(", ");

                if (parameter.IsOutput)
                    b.AppendFormat("out {0}Output", parameter.Name);
                else
                {
                    if (parameter.IsTableValue)
                    {
                        b.AppendFormat("(IEnumerable<ITableValuedParamRow>)parameters[{0}]", objectIndex.ToString());
                    }
                    else
                    {
                        b.AppendFormat("({1})parameters[{0}]", objectIndex.ToString(), parameter.DataTypes[TypeFormat.DotNetFrameworkType]);
                    }
                    objectIndex++;
                }
            }
            return b.ToString();
        }
        public void ReturnVariableNoSelectTest()
        {
            // Arrange
            var helper = new ProcedureHelper();
            var procedure = new Procedure("proc", "proc", null, null, null);

            // Act
            var result = helper.GetReturnVariable(procedure);

            // Assert
            Assert.AreEqual("int result;", result);
        }
 /// <summary>
 /// Gets the variable declaration statement for the return value.
 /// </summary>
 /// <param name="proc">The procedure to get the return variable declaration statement.</param>
 /// <returns>
 /// The generated declaration statement.
 /// </returns>
 public string GetReturnVariable(Procedure proc)
 {
     var returnType = GetReturnType(proc);
     if (proc.Selects.Count() == 1 && proc.Selects.First().IsSingleRow && proc.Selects.First().Columns.Count() == 1)
         return string.Format("{0} result = default({0});", returnType);
     else if (proc.Selects.Any())
         return string.Format("{0} result = new {0}();", returnType);
     else
         return string.Format("{0} result;", returnType);
 }
        public void ReturnVariableSingleSelectTest()
        {
            // Arrange
            var helper = new ProcedureHelper();
            var procedure = new Procedure("proc", "proc", null, null, new List<Select>{
                new Select(new List<SelectColumn>{
                  new SelectColumn("col1", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Int32?"), true),
                  new SelectColumn("col2", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "String"), true)
                }, false, null)
            });

            // Act
            var result = helper.GetReturnVariable(procedure);

            // Assert
            Assert.AreEqual("Result<IEnumerable<procOutputDto>> result = new Result<IEnumerable<procOutputDto>>();", result);
        }
 /// <summary>
 /// Gets the generated SqlParameter objects with assigned values.
 /// </summary>
 /// <param name="proc">The procedure to get the generated SqlParameters for.</param>
 /// <param name="indent">The number of tabs to indent the generated code.</param>
 /// <returns>
 /// The generated SqlParameters
 /// </returns>
 public string GetSqlParamList(Procedure proc, int indent = 0)
 {
     var b = new TextBuilder();
     b.Indent(indent);
     for (var i = 0; i < proc.Parameters.Count(); i++)
     {
         var parameter = proc.Parameters.ElementAt(i);
         if (parameter.IsTableValue)
         {
             b.AppendFormatLine("cmd.Parameters.Add(\"{0}\", SqlDbType.Structured).Value = {0}.Select(s => s.ToSqlDataRecord());", parameter.Name);
         }
         else
         {
             if (!parameter.IsOutput)
             {
                 b.AppendFormatLine("cmd.Parameters.Add(\"{0}\", SqlDbType.{1}).Value = (object){0} ?? DBNull.Value;", parameter.Name, parameter.DataTypes[TypeFormat.SqlDbTypeEnum]);
             }
             else
             {
                 b.AppendFormatLine("var {0}OutputParameter = new SqlParameter(\"{0}\", SqlDbType.{1}) {{ Direction = ParameterDirection.Output }};", parameter.Name, parameter.DataTypes[TypeFormat.SqlDbTypeEnum]);
                 b.AppendFormatLine("cmd.Parameters.Add({0}OutputParameter);", parameter.Name);
             }
         }
     }
     return b.ToString();
 }
        public void SqlParameterTest()
        {
            // Arrange
            var helper = new ProcedureHelper();
            var procedure = new Procedure("proc", "proc", null, new List<Parameter> {
                new Parameter("param1", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Int32?"), false, null),
                new Parameter("param2", DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Int32?"), true, null)
            }, null);

            // Act
            var result = helper.GetSqlParamList(procedure);

            // Assert
            Assert.AreEqual(@"cmd.Parameters.Add(""param1"", SqlDbType.Int).Value = (object)param1 ?? DBNull.Value;
            var param2OutputParameter = new SqlParameter(""param2"", SqlDbType.Int) { Direction = ParameterDirection.Output };
            cmd.Parameters.Add(param2OutputParameter);
            ", result);
        }