C# stored procedure without passing optional parameters - c#

My stored procedure in SQL Server looks like this:
ALTER PROC [dbo].[Rd_CreateModifyAssignmentType]
(
#AssignmentTypeId nvarchar(50),
#AssignmentTypeName nvarchar(50),
#mode int,
#Langtype nvarchar(10)=''
)
While calling it from C# like this:
SqlHelper.ExecuteNonQuery("Rd_CreateModifyAssignmentType", AssignmentTypeId, AssignmentTypeName, mode);
it throws an exception:
Parameter count does not match Parameter Value count.
I want to call the procedure in C# without passing optional parameters.
Please help me with this.

In your code you can write as:
if (Langtype.HasValue)
cmd.Parameters.AddWithValue("#Langtype", Langtype.Value);
So now what will happen is that your procedure will check for the value of optional parameter. If it will not find any value then the method is not going to add the #Langtype parameter into the command and it will use the default value as '' which you have specified in your database.

Please set default value by null all parameter in stored procedure:
ALTER PROC [dbo].[Rd_CreateModifyAssignmentType]
(
#AssignmentTypeId nvarchar(50) = null,
#AssignmentTypeName nvarchar(50) = null,
#mode int = null,
#Langtype nvarchar(10) = null
)

Related

EF6 stored procedure must declare scalar variable

I am trying to call a stored procedure using C# EF6 to bring back data. I have tried to run the stored procedure in SQL management studio and it seems to work fine, however when I try to run it in my application I get an error saying "Must declare the scalar variable "#devID"
Here is part of my method in my application calling the stored procedure
public IHttpActionResult GetMetrics(int deviceID, string attribute, string startDate)
{
if (deviceID == 0)
{
return NotFound();
}
var metrics = db.Database.SqlQuery<Metrics>("GetMetrics #devID, #MetricType, #startTime", deviceID, attribute, startDate).ToList();
and here is my stored procedure:
ALTER PROCEDURE [dbo].[GetMetrics]
-- Add the parameters for the stored procedure here
#devID int,
#MetricType nvarchar(20),
#startTime nvarchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT *
FROM dbMetrics
WHERE deviceID = #devID and MetricType = #MetricType and timeStamp >= #startTime
ORDER BY timeStamp
END
As per the documentation, if you want to use named parameters, you need to pass SqlParameter objects like this:
var metrics = db.Database.SqlQuery<Metrics>("GetMetrics #devID, #MetricType, #startTime",
new SqlParameter("devID", deviceID),
new SqlParameter("MetricType", attribute),
new SqlParameter("startTime", startDate)
).ToList();

Adding new parameter to stored procedure

I have a stored procedure in my database that currently takes in and utilizes 11 parameters (all working great). I need to add a new parameter to this for a new column I added.
We always explicitly define our columns in code, so there was no issue adding a column to the end of the table. However, if I add a new parameter in my stored procedure to populate this new column, will it throw an error back to my C# code if it isn't supplied, or will it default to null (or some other value) for the parameter?
Example C# code to call the stored procedure:
public static void InsertMailLog(string messageId, DateTime sentOrReceivedDate,
string fromAddress, string toAddress, string subject, string receivedMessage, string tailNumber,
string messageType, string direction, string sentOrReceived, string distributionList, ILogger AppEventLog, string filename = null)
{
List<string> lstParameterValues = new List<string>();
try
{
lstParameterValues.Add(messageId ?? "");
lstParameterValues.Add(sentOrReceivedDate.ToString("yyyy-MM-dd HH:mm:ss.fff"));
lstParameterValues.Add(fromAddress ?? "");
lstParameterValues.Add(toAddress);
lstParameterValues.Add(subject ?? "");
lstParameterValues.Add(receivedMessage ?? "");
lstParameterValues.Add(tailNumber ?? "");
lstParameterValues.Add(messageType ?? "");
lstParameterValues.Add(direction ?? "");
lstParameterValues.Add(sentOrReceived ?? "");
lstParameterValues.Add(distributionList ?? "");
lstParameterValues.Add(filename ?? ""); //THIS IS NEW, but it has not been published yet as the SP hasn't been updated.
CommonDAL.ExecSpNonQuery("spMailLogInsert", lstParameterValues);
}
catch (Exception ex)
{
CommonBLL.LogError(ex, MethodBase.GetCurrentMethod().DeclaringType.Name, MethodBase.GetCurrentMethod().Name, "Error", messageId, tailNumber, messageType, "", Settings.Default.ContentProvider, AppEventLog);
}
}
Example stored procedure code:
ALTER PROCEDURE [dbo].[spMailLogInsert]
#SdMessageId varchar(50),
#SentOrReceivedDate datetime,
#FromAddress varchar(100),
#ToAddress varchar(100),
#Subject varchar(255),
#Message varchar(MAX),
#TailNumber varchar(50),
#MessageType varchar(50),
#Direction varchar(50),
#SentOrReceived varchar(50),
#DistributionList varchar(50),
#Filename varchar(50) --THIS IS NEW
AS
SET NOCOUNT ON
INSERT MailLog (SdMessageId, SentOrReceivedDate, FromAddress, ToAddress,
[Subject], [Message], TailNumber, MessageType, Direction,
SentOrReceived, DistributionList, Filename --THIS IS NEW
)
VALUES (#SdMessageId, #SentOrReceivedDate, #FromAddress, #ToAddress,
#Subject, #Message, #TailNumber, #MessageType,
#Direction, #SentOrReceived, #DistributionList,
#Filename --THIS IS NEW
)
I completely understand that this is a terrible use of a stored procedure. I should be using Entity Framework, but it's already written, and I have a project to update the entire project to use EF in the DAL at a later date (this is very old code).
My question is, if I add the new parameter #Filename" to the stored procedure before the new C# code above gets published, will I get an error, or will the stored procedure parameter simply default to NULL? Or, if someone has a better way to default this to NULL or empty string, if it isn't supplied, I'm all ears.
Either Make it nullable like this.
ALTER PROCEDURE [dbo].[spMailLogInsert]
#SdMessageId varchar(50),
#SentOrReceivedDate datetime,
#FromAddress varchar(100),
#ToAddress varchar(100),
#Subject varchar(255),
#Message varchar(MAX),
#TailNumber varchar(50),
#MessageType varchar(50),
#Direction varchar(50),
#SentOrReceived varchar(50),
#DistributionList varchar(50),
#Filename varchar(50) = NULL --THIS IS NEW
......
Or Add a Default value like this:
ALTER PROCEDURE [dbo].[spMailLogInsert]
#SdMessageId varchar(50),
#SentOrReceivedDate datetime,
#FromAddress varchar(100),
#ToAddress varchar(100),
#Subject varchar(255),
#Message varchar(MAX),
#TailNumber varchar(50),
#MessageType varchar(50),
#Direction varchar(50),
#SentOrReceived varchar(50),
#DistributionList varchar(50),
#Filename varchar(50) = 'abc.txt' --THIS IS NEW
......
You could go ahead with the SP and just use a default parameter. https://technet.microsoft.com/en-US/library/ms189330(v=SQL.105).aspx
#Filename varchar(50) = NULL --THIS IS NEW
Based on your Stored Procedure it is considered required. To avoid it being required, you should add the following to your parameter:
#Filename varchar(50) = null
That will make it optional, which will allow you to avoid excessive Null checks in your code behind. Which can make your code turn to spaghetti quickly. This would be the easiest and least intrusive approach to solve your issue.
I completely understand that this is a terrible use of a stored procedure.
Er, no? It's a simple sproc, sure, but if all your SQL are sprocs, then this is the way to go.
I should be using Entity Framework [...]
Things in programming aren't always optimal, and you have to do what you have to do.
[...] if I add the new parameter "Filename" to the stored procedure before the new C# code above gets published, will I get an error, or will the SP simply default to NULL?
SQL will throw an error that the new parameter wasn't supplied through it's caller (ASP.Net). See here.
CREATE PROCEDURE Sales.uspGetSalesYTD
#SalesPerson nvarchar(50) = NULL -- NULL default value
AS
You should use a default value or it will get an error

Stored procedure has too many parameters when being called [duplicate]

This question already has answers here:
"Procedure or function has too many arguments specified" But It Doesn't
(3 answers)
Closed 8 years ago.
I have a stored procedure with parameters:
ALTER PROCEDURE [dbo].[prAddSortament]
#Name varchar(255),
#ProcessingId varchar(35),
#ShapeId varchar(35),
#GostId varchar(35),
#PartOfId varchar(35),
#DescrArr varchar(max),--varbinary,
#tsVal varchar(max),
#SM varchar(max)
AS
BEGIN
And I'm calling it from my program that way:
using (SqlConnection con = new SqlConnection(Properties.Settings.Default.MiSConStr))
{
SqlCommand cmd = new SqlCommand("dbo.prAddSortament", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Name", sort.Name);
cmd.Parameters.AddWithValue("#ProcessingId", sort.Processing.ObjectId);
cmd.Parameters.AddWithValue("#ShapeId", sort.Shap.ObjectId);
cmd.Parameters.AddWithValue("#GostId", sort.Gost);
cmd.Parameters.AddWithValue("#PartOfId", sort.PartOf);
cmd.Parameters.AddWithValue("#DescrArr", sort.Description);
cmd.Parameters.AddWithValue("#tsVal", ts);
cmd.Parameters.AddWithValue("#SM", sortMat);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
On cmd.ExeccutrNonQuery(); I have an exception
Procedure or function prAddSortament has too many arguments specified.
Can anybody help me?
If the number of parameters are same then try to check their types. It looks like there is some mismatch of the data types of the parameters.
Add below code it will specify the stored procedure you want to add :-
cmd.CommandText = "prAddSortament";
Extra info for this kind of error as detailed here http://www.sql-server-helper.com/error-messages/msg-8144.aspx :-
SQL Server Error Messages - Msg 8144
Error Message: Server: Msg 8144, Level 16, State 2, Procedure Stored
Procedure or Function Name, Line 0 Procedure or function Stored
Procedure or Function Name has too many arguments specified.
Causes:
As the message describes, this error is encountered when you are
passing arguments or parameters to a function or stored procedure
which is more than what the function or stored procedure is expecting.
To illustrate, let’s say you have the following function definition:
> CREATE FUNCTION [dbo].[ufn_Concat] ( #pString1 VARCHAR(10), #pString2
> VARCHAR(10) ) RETURNS VARCHAR(20) AS BEGIN
> RETURN ISNULL(#pString1 + ' ', '') + ISNULL(#pString2, '') END
This function expects only 2 arguments, namely #pString1 and
> #pString2. To use this function, you do the following: SELECT
> [dbo].[ufn_Concat] ( [FirstName], [LastName] ) AS [FullName] FROM
> [dbo].[Customers]
The error will be encountered you pass more than 2 arguments or
> parameters to the function, as follows: SELECT [dbo].[ufn_Concat] (
> [FirstName], [MiddleName], [LastName] ) AS [FullName] FROM
> [dbo].[Customers]
>
Server: Msg 8144, Level 16, State 2, Line 1 Procedure or function
dbo.ufn_Concat has too many arguments specified.
Solution/Workaround:
To avoid this error from happening, always make sure that you pass the
same number of arguments that a stored procedure or function is
expecting. To know the parameters expected by a stored procedure, you
can use the sp_help system stored procedure and pass the name of the
stored procedure as the parameter.
That was my great fault. I'm using two versions of database, and in the connection string was specified old version of DB, where dbo.prAddSortament exists but have less parameters.

Parameter does not exist as a stored procedure parameter

ALTER PROCEDURE [dbo].[SelectCompletionNonCompletionCourseReport]
#LearnerName NVARCHAR(510) = NULL,
#ManagerId INT = NULL,
#CourseId INT = NULL,
#StartDateFrom SMALLDATETIME = NULL,
#StartDateTo SMALLDATETIME = NULL,
#TeamList XML = NULL,
#JobID NVARCHAR(max)=NULL,
#CourseStatus NVARCHAR(20)=NULL,
#ReportAdminID INT=0,
#ReportTeamList NVARCHAR(max)=NULL,
#RowsTotal int = 0,
#PageIndex int = 1,
#RowsPerPage int = 10
AS
BEGIN
DECLARE #TblCrieiria TABLE
(
id INT IDENTITY(1, 1),
areacode NVARCHAR(11),
regioncode NVARCHAR(11),
teamcode NVARCHAR(11)
)
IF #TeamList IS NULL
BEGIN
INSERT INTO #TblCrieiria VALUES(NULL,NULL,NULL)
END
BEGIN
This is the beginning of the procedure...
using (Database db = new Database(DScape.DAL.Config.ConfignPropertyName.DSCAPELMS_CONNECTION_STRING_NAME))
{
var cmd = new SqlCommand
{
CommandText = "SelectCompletionNonCompletionCourseReport",
CommandType = CommandType.StoredProcedure
};
cmd.Parameters.AddWithValue("#LearnerName", LearnerName);
cmd.Parameters.AddWithValue("#ManagerId", ManagerId);
cmd.Parameters.AddWithValue("#CourseId", CourseId);
cmd.Parameters.AddWithValue("#StartDateFrom", StartDateFrom);
cmd.Parameters.AddWithValue("#StartDateTo", StartDateTo);
cmd.Parameters.AddWithValue("#TeamList", TeamList);
cmd.Parameters.AddWithValue("#JobID", JobID);
cmd.Parameters.AddWithValue("#CourseStatus", CourseStatus);
cmd.Parameters.AddWithValue("#ReportAdminID", ReportAdminID);
cmd.Parameters.AddWithValue("#ReportTeamList", ReportTeamList);
cmd.Parameters.AddWithValue("#PageIndex", 1);
DataSet dsClient = db.GetDataSet(cmd);
if (dsClient.Tables.Count > 0)
return dsClient.Tables[0];
else
return null;
}
This is the method which communicates with the procedure, and it gaves me an error
Parameter does not exist as a stored procedure parameter/ function/procedure take too many arguments...
It's about #PageIndex parameter. Doesn't matter what is the value, we don't talk for values here but for parameter which is defined in the stored procedure but doesn't work?
And for the record, this problem did pop-up today w/o any code writing/modifying just appeared as I tried to do that report, when yesterday it was all good...I have a teammate which is next to me with absolute the same code both in sql and c# and it works just fine on his pc, but mine throws this errors, I'm trying to resolve this from 3 hours and I am completely out of answers , so please give me direction in which should I continue to resolve this .....................
and I say again, the problem is not from the connection to DB or type of the parameter or the value, the error is committed with the parameter itself - does not exist in the procedure, which is insane in my opinion.
Given that all parameters are optional, you are not required to explicitly provide any of them from your client code. Default values will be provided for you by SQL Server. The contract explictly states it in the stored procedure's signature.
An optional parameter is exactly that: optional. If you had provided the incorrect number of parameters, SQL Server would have returned a different error, indicating that the number of parameters was incorrect. This is not the case. Instead, you are seeing that you are asking for a parameter that is undefined, which indicates that the stored procedure signature you think you are calling does not match the stored procedure signature you are actually calling.
Verify that you are both connecting to the same database instance. If you are not, verify that the stored procedure is identical on both database instances.
parameter count doesnt match. check the params again.
You have to send parameters for rowstotal and rowsperpage as well because you have declared them at the top before "begin" clause.
If you do not want to send that params and they will be just constant, please declare them below as variable or constant, not a parameter.
i.e.
CREATE PROCEDURE DeleteById
#TableName sysname,
#Id int
AS
BEGIN
DECLARE #StrId AS VARCHAR(50)
SET #StrId = CONVERT(VARCHAR(50), #Id)
--any sp code here
END
Hope this helps.

SQL Scope_Identity is returning 0 or -1

I'm having issues getting the last row affected ID, it's returning 0, this means that it has an error on format being inserted. I executed the stored procedure and added the values manually, it return'd the correct ID. But when I try to do it with the code it keeps returning 0 or -1 ... I tried this last night after several hours and I'm already confused with the values it gave me.
C#:
conn.Open();
cmd.Parameters.AddWithValue("#fileName", fileName);
cmd.Parameters.AddWithValue("#filePrivacy", filePrivacy);
cmd.Parameters.AddWithValue("#filePassword", filePassword);
cmd.Parameters.AddWithValue("#fileDescription", fileDesc);
cmd.Parameters.AddWithValue("#fileOwner", fileOwner);
cmd.Parameters.AddWithValue("#fileDate", DateTime.Now);
cmd.Parameters.AddWithValue("#fileExpire", DateTime.Now.AddMinutes(fileExpire));
cmd.Parameters.AddWithValue("#fileCodeText", fileType);
var fileID = cmd.Parameters.Add("#fileID", SqlDbType.Int);
fileID.Direction = ParameterDirection.Output;
int returnfileID = (int)cmd.ExecuteScalar();
return returnfileID;
Stored Procedure:
CREATE PROCEDURE [dbo].[Upload]
#fileName nvarchar(20),
#filePrivacy int,
#filePassword nvarchar(50),
#fileDescription nvarchar(200),
#fileOwner nvarchar(14),
#fileDate smalldatetime,
#fileExpire smalldatetime,
#fileCodeText int,
#fileID int out
AS
INSERT INTO Files ([FileName], FilePrivacy, FilePassword, FileDescription, FileOwner, FileDate, FileExpire, FileCodeText)
VALUES (#fileName, #filePrivacy, #filePassword, #fileDescription, #fileOwner, #fileDate, #fileExpire, #fileCodeText)
SET #fileID = SCOPE_IDENTITY()
RETURN #fileID
SQL Table:
CREATE TABLE [dbo].[Files] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[FileName] NVARCHAR (20) NOT NULL,
[FilePrivacy] INT NOT NULL,
[FilePassword] NVARCHAR (50) NULL,
[FileDescription] NVARCHAR (200) NULL,
[FileOwner] NVARCHAR (14) NOT NULL,
[FileDate] SMALLDATETIME NOT NULL,
[FileExpire] SMALLDATETIME NOT NULL,
[FileCodeText] INT NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
ExecuteScalar 'Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored'
If you select #fileID (instead of return) it should work.
Alternatively you could access the #fileID parameter value after you execute the query, in which case there's no real point having an ExecuteScalar, you could change it to to ExecutenonQuery.
Use in the SQL
SET #fileID= SCOPE_IDENTITY() RETURN #fileID
SELECT ##IDENTITY;
and in the C# code
int returnfileID = Convert.ToInt32(cmdInsert.ExecuteScalar())
My initial thought is that you are getting back the stored procedure return code. #fileID should be returned by your stored procedure since you have set it as an OUTPUT parameter. Remove the RETURN from your stored procedure. It should pass back the output variable rather than the execution code that way.

Categories