Because the value of your parameter is set to an empty string, and you don't set the parameter's
Size
property, the parameter defaults to
nvarchar(1)
.
As a result, your code will only return the first character of the output parameter value.
The quick fix is to set
Size = -1
on the output parameter.
case "Output":
Cmd.Parameters[entry.Key].Direction = ParameterDirection.Output;
Cmd.Parameters[entry.Key].Size = -1;
break;
There are various other improvements you could make. For example, your code will currently only work if you have a parameter called
@parmRecID
, and it will only return the value of that parameter. Any other output parameters will be ignored.
You should also use
SCOPE_IDENTITY
within your stored procedure, rather than selecting the maximum ID.
SCOPE_IDENTITY (Transact-SQL) - SQL Server | Microsoft Docs[
^]
Here's a start:
public class ParameterValue
{
public object Value { get; set; }
public string Direction { get; set; } = "Input";
public int? Size { get; set; }
}
public class SQLDatabase
{
private readonly string _connectionString;
public SQLDatabase(string connectionString)
{
_connectionString = connectionString;
}
public SQLDatabase() : this("Data Source=DESKTOP-EL4GU86;Integrated Security=true")
{
}
public int ExecuteNonQuery(string database, string commandText, IReadOnlyDictionary<string, ParameterValue> parameters, CommandType commandType = CommandType.StoredProcedure)
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
connection.ChangeDatabase(database);
using (var command = new SqlCommand(commandText, connection))
{
command.CommandType = commandType;
var outputParameters = new Dictionary<SqlParameter, ParameterValue>();
foreach (var pair in parameters)
{
var param = command.Parameters.AddWithValue(pair.Key, pair.Value.Value);
if (pair.Value.Size != null) param.Size = pair.Value.Size.GetValueOrDefault();
switch (pair.Value.Direction)
{
case "Output":
{
param.Direction = ParameterDirection.Output;
outputParameters.Add(param, pair.Value);
break;
}
case "ReturnValue":
{
param.Direction = ParameterDirection.ReturnValue;
outputParameters.Add(param, pair.Value);
break;
}
}
}
int result = command.ExecuteNonQuery();
foreach (var pair in outputParameters)
{
pair.Value.Value = pair.Key.Value;
}
return result;
}
}
}
}
Usage:
var db = new SQLDatabase();
const string theDatabase = "CustomerDB";
const string commandText = "usp_AddCustomer";
var parameters = new Dictionary<string, ParameterValue>
{
["@paramFirstName"] = new ParameterValue { Value = TxtFirstName.Text, Size = 50 },
["@paramLastName"] = new ParameterValue { Value = TxtLastName.Text, Size = 50 },
["@paramAddress"] = new ParameterValue { Value = TxtAddress.Text, Size = 50 },
["@paramCity"] = new ParameterValue { Value = TxtCity.Text, Size = 50 },
["@paramZipCode"] = new ParameterValue { Value = TxtZipCode.Text, Size = 50 },
["@paramRecID"] = new ParameterValue { Direction = "Output", Size = -1 }
};
db.ExecuteNonQuery(theDatabase, commandText, parameters);
object RecID = parameters["@paramRecID"].Value;
MessageBox.Show("From FrmMain, RecID is " + RecID);
Stored procedure:
CREATE OR ALTER PROCEDURE [dbo].[usp_AddCustomer]
(
@parmFirstName As varchar(50),
@parmLastName As varchar(50),
@parmAddress As varchar(50),
@parmCity As varchar(50),
@parmZipCode As varchar(50),
@parmRecID As int OUTPUT
)
As
If Exists
(
SELECT *
FROM dbo.SmallCustomerTable
WHERE FirstName = @parmFirstName
And LastName = @parmLastName
And Address = @parmAddress
)
BEGIN
SET @paramRecID = 0;
END
Else
BEGIN
INSERT INTO dbo.SmallCustomerTable (FirstName, LastName, Address, City, ZipCode)
VALUES (@parmFirstName, @parmLastName, @parmAddress, @parmCity, @parmZipCode);
SET @paramRecID = SCOPE_IDENTITY();
END;
GO