I am building a .NET Core 3.1 Web API that uses stored procedures.
One of the stored procedures takes input and select values from a form and returns a ticket once the form is submitted in the front end.
My SQL Server stored procedure that looks like this:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[CallSummaryAddO]
#SedonaUser NVarCHar(100),
#SystemID Int,
#ProblemID Int,
#ResolutionID Int,
#NextStepID Int,
#CustomerComments NVaRChar(1000),
#TechNotes NVaRChar(1000),
#CustomerOnCall NVarChar(200),
#CustomerCallBackPhone NVarChar(15)
AS
DECLARE #ServiceTicketID Int,
#CustomerID Int,
#CustomerSiteID Int,
#NextTechID Int,
#TicketStatus NVarCHar(10),
#Today DateTime,
#ClosedDate DateTime,
#ServiceLevel Int,
#Route Int,
#AutoNotify NVarChar(320)= '',
#CustomerBillID Int,
#ServiceCoordinator Int = 1,
#TicketNumber Int,
#TicketNumberAdded Int
EXEC Sandbox.dbo.Service_Ticket_Next #TicketNumber Output
SET #TicketNumberAdded = #TicketNumber
SET #TicketStatus = CASE WHEN #ResolutionID = 1 THEN 'OP' ELSE 'CL' END
SET #ClosedDate = CASE WHEN #ResolutionID = 1 THEN '1899-12-30' ELSE GETDATE() END
SELECT
#CustomerID = S.Customer_id,
#CustomerSiteID = S.Customer_Site_id,
#ServiceLevel = Service_Level_Id,
#Route = Route_Id,
#CustomerBillID = Ste.Customer_Bill_Id
FROM
Sandbox.dbo.ar_customer_system S
INNER JOIN
Sandbox.dbo.ar_customer_site ste ON ste.Customer_Site_Id = S.Customer_Site_Id
WHERE
Customer_System_Id = #SystemID
SET #Today = GETDATE()
SET #ServiceCoordinator = #NextStepID
INSERT INTO Sandbox.dbo.[SV_Service_Ticket]
([Ticket_Status],[Ticket_Number],[Customer_Id],[Customer_Site_Id],[Customer_System_Id]
,[Multiple_Systems],[Creation_Date],[Requested_By],[Requested_By_Phone],[Problem_Id]
,[Scheduled_For],[Last_Service_Tech_Id],[Estimated_Length],[Resolution_Id],[Billable]
,[Billed],[Equipment_Charge],[Labor_Charge],[Other_Charge],[TaxTotal],
[Regular_Hours],[Overtime_Hours],[Holiday_Hours],[Trip_Charge],[Invoice_Id],[Regular_Rate],[Overtime_Rate],[Holiday_Rate],[Bypass_Warranty],[Bypass_ServiceLevel],[IsInspection]
,[ClosedDate],[Manual_Labor],[Service_Company_Id],[Priority_Id],[Category_Id],[Expertise_Level]
,[Entered_By],[Invoice_Contact],[Signer],[Remittance],[Signature_Image],[Payment_Received]
,[Sub_Problem_Id],[Service_Level_Id],[UserCode],[Edit_Timestamp],[PO_Number],[CustomerComments],[Number_Of_Dispatches],[Route_Id]
,[Sub_Customer_Site_ID],[Customer_CC_Id],[Customer_Bank_Id],[Ticket_Status_Id],[Customer_EFT_Id],[Auto_Notify]
,[Customer_Bill_Id],[Customer_Contact_Id],[Requested_By_Phone_Ext] ,[Inspection_Id],[Service_Ticket_Group_Id]
,[Service_Coordinator_Employee_Id],[Resolved_Date],[Inspection_Incremented],[OPT_rowguid],[Bypass_TicketServiceCompany]
,[EntrySource])
VALUES
(#TicketStatus, #TicketNumber,#CustomerID, #CustomerSiteID, #SystemID,
'N', #Today, #CustomerOnCall, #CustomerCallBackPhone, #ProblemID,
'1899-12-30', 1, 60, #ResolutionID, 'N',
'', 0,0,0,0,
0,0,0,0,1,0,0,0,'N','N','N',
#ClosedDate,'N',56,2,2,3,
#SedonaUser,'','','N','0x4E6F205369676E6174757265204F6E2046696C65','N',
1,#ServiceLevel,#SedonaUser,#Today,'', #CustomerComments,0,#Route,
1,0,0,1,1,#AutoNotify,#CustomerBillID,1,'',1,1,#ServiceCoordinator,#ClosedDate,'N',NewID(),'N','Service')
SET #ServiceTicketID = ##IDENTITY
INSERT INTO Sandbox.dbo.SV_Service_Ticket_Notes (Service_Ticket_Id, Notes, Access_Level, UserCode, Entered_Date, Edit_UserCode, Edit_Date, Is_Resolution)
VALUES (#ServiceTicketID, #TechNotes,1,#SedonaUser, #Today, #SedonaUser, #Today, Case When #TicketStatus = 'CL' then 'Y' else 'N' end)
DECLARE #UserComments NVarChar(100)
SET #UserComments = 'Added Service Ticket ' + CONVERT(NVarChar,#TicketNumber)
INSERT INTO Sandbox.dbo.SY_Edit_Log (UserCode, Edit_Timestamp, TableName, Edit_Type_AUD, KeyField, KeyData, UserComments, SystemComments, Edit_Column_Name, OldData, NewData)
VALUES (#SedonaUser, #Today, 'SV_Service_Ticket', 'A', 'Ticket_Number', #TicketNumber, #UserComments, '','','','')
IF #TicketStatus = 'CL'
BEGIN
SET #UserComments = 'Closed Service Ticket ' + CONVERT(NVarChar,#TicketNumber)
INSERT INTO Sandbox.dbo.SY_Edit_Log (UserCode, Edit_Timestamp, TableName, Edit_Type_AUD, KeyField, KeyData, UserComments, SystemComments, Edit_Column_Name, OldData, NewData)
VALUES (#SedonaUser, #Today, 'SV_Service_Ticket', 'U', 'Ticket_Number', #TicketNumber, #UserComments, '','','','')
END
RETURN #TicketNumberAdded
My repository looks like this:
public async Task<CallSummaryAddResult> InsertCallSummaryAddResult(CallSummaryAddResult callSummaryAddResult)
{
using (SqlConnection sql = new SqlConnection(_connectionString))
{
using (SqlCommand cmd = new SqlCommand("dbo.CallSummaryAddO", sql))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#SedonaUser", SqlDbType.NVarChar)).Value = callSummaryAddResult.SedonaUser;
cmd.Parameters.Add(new SqlParameter("#SystemID", callSummaryAddResult.SystemID));
cmd.Parameters.Add(new SqlParameter("#ProblemID", callSummaryAddResult.ProblemID));
cmd.Parameters.Add(new SqlParameter("#ResolutionID", callSummaryAddResult.ResolutionID));
cmd.Parameters.Add(new SqlParameter("#NextStepID", callSummaryAddResult.NextStepID));
cmd.Parameters.Add(new SqlParameter("#CustomerComments", SqlDbType.NVarChar)).Value = callSummaryAddResult.CustomerComments;
cmd.Parameters.Add(new SqlParameter("#TechNotes", SqlDbType.NVarChar)).Value = callSummaryAddResult.TechNotes;
cmd.Parameters.Add(new SqlParameter("#CustomerOnCall", SqlDbType.NVarChar)).Value = callSummaryAddResult.CustomerOnCall;
cmd.Parameters.Add(new SqlParameter("#CustomerCallBackPhone", SqlDbType.NVarChar)).Value = callSummaryAddResult.CustomerCallBackPhone;
//cmd.Parameters.Add(new SqlParameter("#TicketNumber", SqlDbType.Int));
//cmd.Parameters["#TicketNumber"].Direction = ParameterDirection.Output;
await sql.OpenAsync();
await cmd.ExecuteNonQueryAsync();
_callSummaryAddResults.Add(callSummaryAddResult);
return callSummaryAddResult;
}
}
}
When I execute this in SSMS, I am getting a new ticket number, but in code, I am only getting 0 back. I want to display the actual returned ticket number and not a 0 or 1 (success or failure).
My job is to return the TicketNumber and display this to the end-user once available. How can I make this happen?
Thanks in advance.
I am trying to load output parameters from my SQL stored procedure.
USE [EdiMon_Beta]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetClients]
-- Add the parameters for the stored procedure here
#sender nvarchar(max),
#subSender nvarchar(max),
#receiver nvarchar(max),
#subReceiver nvarchar(max),
#msgTypeID int,
#ErrorMsg nvarchar(max) = null OUTPUT,
#processId int = 0 OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE
#senderId int,
#subSenderId int,
#receiverId int,
#subReceiverId int
SELECT
#senderId = ID
FROM [dbo].[Party_Client]
WHERE
[Number] LIKE #sender
IF(#senderId IS NULL)
BEGIN
SET #ErrorMsg = 'Sender does not exist'
RETURN ;
END
SELECT
#subSenderId = ID
FROM [dbo].[Party_Client]
WHERE
[Number] LIKE #subSender
AND ParentId = #senderId
AND IsSubClient = 1
IF(#subSenderId IS NULL)
BEGIN
SET #ErrorMsg = 'SubSender does not exist'
RETURN ;
END
SELECT
#receiver = ID
FROM [dbo].[Party_Client]
WHERE
[Number] LIKE #receiver
IF(#receiverId IS NULL)
BEGIN
SET #ErrorMsg = 'Receiver does not exist'
RETURN;
END
SELECT
#subReceiverId = ID
FROM [dbo].[Party_Client]
WHERE
[Number] LIKE #subReceiver
AND ParentId = #receiverId
AND IsSubClient = 1
IF(#subReceiverId IS NULL)
BEGIN
SET #ErrorMsg = 'SubReceiver does not exist'
RETURN ;
END
SELECT #processId = ID FROM [dbo].[Party_Processes]
WHERE MsgTypeId = #msgTypeID
AND SenderId = #senderId
AND ReceiverId = #receiverId
END
And reading it with c# code:
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
SqlCommand command = new SqlCommand("GetClients", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#sender", sender));
command.Parameters.Add(new SqlParameter("#subSender", subSender));
command.Parameters.Add(new SqlParameter("#receiver", receiver));
command.Parameters.Add(new SqlParameter("#subReceiver", subReceiver));
command.Parameters.Add(new SqlParameter("#msgTypeID", msgTypeID));
var errorMsgParam = command.Parameters.Add(new SqlParameter("#ErrorMsg", SqlDbType.NVarChar, -1));
errorMsgParam.Direction = ParameterDirection.Output;
var processIdParam = command.Parameters.Add(new SqlParameter("#processId", SqlDbType.Int, -1));
processIdParam.Direction = ParameterDirection.Output;
connection.Open();
command.ExecuteNonQuery();
var processIDResult = command.Parameters["#processId"].Value;
var errorMsgResult = command.Parameters["#ErrorMsg"].Value;
processID = (int)processIDResult;
errorMsg = errorMsgResult.ToString();
}
}
The thing is, I always get null as result. This is Helper class for xsl mapping in biztalk. All the input parameters are directly from the map. I want to check our database, if these clients exist and also, if process which using them exist.
thanks for your help :)
OK, i solved this. Problem was in 2 or 3 places. For first i had mistake in my SQL stored procedure which is not universal so i didnt post it here (it applies only to my project). The other mistake was in converting my output from stored procedure:
processID = command.Parameters["#processId"].Value as int?;
errorMsg = command.Parameters["#ErrorMsg"].Value == DBNull.Value ? string.Empty : command.Parameters["#ErrorMsg"].Value.ToString();
where processID is declared as "int?" and errorMsg is declared as "string".
Thanks for all the help.
I create stored procedure in T-SQL
CREATE PROCEDURE price_proc #type_of_service int, #date_of_receipt date, #date_of_delivery date, #mechanic_id int, #car_id_p int, #price_for_work float
AS
DECLARE #count int, #car_id int
SELECT #car_id = car_id, #count = COUNT(car_id) FROM work WHERE car_id = #car_id_p GROUP BY car_id
IF(#count > 1 AND #count < 4 )
BEGIN
SET #price_for_work = #price_for_work - (#price_for_work * 0.1)
INSERT INTO work(type_of_service_id, date_of_receipt, date_of_delivery, mechanic_id, car_id, price_for_work) VALUES (#type_of_service, #date_of_receipt, #date_of_delivery, #mechanic_id, #car_id_p, #price_for_work)
END
ELSE IF(#count > 4)
BEGIN
SET #price_for_work = #price_for_work - (#price_for_work * 0.15)
INSERT INTO work(type_of_service_id, date_of_receipt, date_of_delivery, mechanic_id, car_id, price_for_work) VALUES (#type_of_service, #date_of_receipt, #date_of_delivery, #mechanic_id, #car_id_p, #price_for_work)
END
GO
I call it in my code
string d1 = String.Format("{0:yyyy-MM-dd}", dateTimePicker1.Value);
string d2 = String.Format("{0:yyyy-MM-dd}", dateTimePicker2.Value);
cmd = new SqlCommand("price_proc", SqlConn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#type_of_service", SqlDbType.Int)).Value = type_of_service_id;
cmd.Parameters.Add(new SqlParameter("#date_of_receipt", SqlDbType.Date)).Value = d1;
cmd.Parameters.Add(new SqlParameter("#date_of_delivery", SqlDbType.Date)).Value = d2;
cmd.Parameters.Add(new SqlParameter("#mechanic_id", SqlDbType.Int)).Value = mechanic_id;
cmd.Parameters.Add(new SqlParameter("#car_id_p",SqlDbType.Int)).Value = car_id;
cmd.Parameters.Add(new SqlParameter("#price_for_work", SqlDbType.Float)).Value = price;
cmd.ExecuteNonQuery();
But it does not work? I print cmd.ExecuteNonQuery() and give -1. Help me please.
You either need to Select a result set, or return an integer from your stored procedure. By the looks of your code, I imagine you may wish to return the SCOPE_IDENTITY, which will equal the newly inserted ID.
I have written a SQL script in stored procedure and query by C#.
But it throws an error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
As I know the problem is that the subquery is returning more than one row to the main query. May I know how to solve it? Thank you.
public void insertData(string TransID, string Item, string FromLocation, string Qty, string Requestor, string RefNum, string Remark, string ReasonID, string ReasonRemark, string CreateDate, string CreateUser, string ToLocation)
{
string constr = ConfigurationManager.ConnectionStrings["CIMProRPT01ConnectionString"].ConnectionString;
using (SqlConnection _cn = new SqlConnection(constr))
{
using (SqlCommand _cmd = new SqlCommand("MMSIssue_InsertOrUpdate", _cn))
{
using (SqlDataAdapter da = new SqlDataAdapter(_cmd))
{
_cn.Open();
_cmd.CommandType = CommandType.StoredProcedure;
_cmd.Parameters.AddWithValue("#INV_TRANS_ID", TransID);
_cmd.Parameters.AddWithValue("#INV_ID", Item);
_cmd.Parameters.AddWithValue("#INV_LOCATION", FromLocation);
_cmd.Parameters.AddWithValue("#INV_QTY", Qty);
_cmd.Parameters.AddWithValue("#INV_TRANS_REQUESTOR", Requestor);
_cmd.Parameters.AddWithValue("#INV_TRANS_REFNO", RefNum);
_cmd.Parameters.AddWithValue("#INV_TRANS_REMARK", Remark);
_cmd.Parameters.AddWithValue("#INV_REASON_ID", ReasonID);
_cmd.Parameters.AddWithValue("#INV_REASON_REMARK", ReasonRemark);
_cmd.Parameters.AddWithValue("#INV_CREATE_DATE", CreateDate);
_cmd.Parameters.AddWithValue("#INV_CREATE_USER", CreateUser);
_cmd.Parameters.AddWithValue("#INV_FROMLOC", ToLocation);
_cmd.Parameters.Add("#RecordFound", SqlDbType.Int, 0);
_cmd.Parameters["#RecordFound"].Direction = ParameterDirection.Output;
_cmd.ExecuteNonQuery();
string DeleteWMMRSQL = "DELETE FROM [CIMProRPT01].[dbo].[OTH_INV_QTY_LOC] WHERE INV_QTY = 0 OR INV_QTY is null OR INV_QTY <= '-1'";
SqlCommand cmd3 = new SqlCommand(DeleteWMMRSQL, _cn);
cmd3.ExecuteNonQuery();
_cn.Close();
float INV_QTY = Convert.ToInt32(_cmd.Parameters["#RecordFound"].Value.ToString());
if (INV_QTY == 2)
{
//QTY is more Than existing QTY !!");
Response.Write("QTY is more Than existing QTY !!");
Response.Redirect("MMS_LocationTrans.aspx");
}
else
{
//QTY not able to key in 0
Response.Write("QTY not able to key in 0!!");
}
}
}
}
}
Stored procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[MMSIssue_InsertOrUpdate]
#INV_TRANS_ID VARCHAR(40),
#INV_ID VARCHAR(40),
#INV_LOCATION VARCHAR(40),
#INV_QTY FLOAT,
#INV_TRANS_REQUESTOR VARCHAR(40),
#INV_TRANS_REFNO VARCHAR(40),
#INV_TRANS_REMARK VARCHAR(255),
#INV_REASON_ID VARCHAR(40),
#INV_REASON_REMARK VARCHAR(255),
#INV_CREATE_DATE DATETIME,
#INV_CREATE_USER VARCHAR (255),
#INV_FROMLOC VARCHAR (40),
#RecordFound INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM OTH_INV_QTY_LOC
WHERE INV_ID = #INV_ID AND INV_LOCATION = #INV_LOCATION)
BEGIN
UPDATE OTH_INV_QTY_LOC
SET [INV_ID] = #INV_ID,
INV_LOCATION = #INV_LOCATION,
INV_QTY = INV_QTY - #INV_QTY
WHERE INV_ID = #INV_ID
AND INV_LOCATION = #INV_LOCATION
INSERT INTO OTH_INV_TRANSACTION (INV_TRANS_ID, INV_ID, INV_TRANS_LOCATION, INV_TRANS_QTY, INV_TRANS_REQUESTOR, INV_TRANS_REFNO, INV_TRANS_REMARK, INV_REASON_ID, INV_REASON_REMARK, INV_CREATE_DATE, INV_CREATE_USER, INV_FROMLOC)
VALUES (#INV_TRANS_ID, #INV_ID, #INV_LOCATION, #INV_QTY, #INV_TRANS_REQUESTOR, #INV_TRANS_REFNO, #INV_TRANS_REMARK, #INV_REASON_ID, #INV_REASON_REMARK, #INV_CREATE_DATE, #INV_CREATE_USER, #INV_FROMLOC)
DECLARE #InvFindQTY FLOAT
SET #InvFindQTY = (SELECT INV_QTY FROM OTH_INV_QTY_LOC)
IF #InvFindQTY >= #INV_QTY
BEGIN
SELECT #RecordFound = 2
END
ELSE
BEGIN
SELECT #RecordFound = 1
END
END
ELSE
BEGIN
SELECT #RecordFound = 0
END
END
The issue is with this line in the stored procedure:
DECLARE #InvFindQTY FLOAT
SET #InvFindQTY = ( SELECT INV_QTY FROM OTH_INV_QTY_LOC)
If you have more than one record in OTH_INV_QTY_LOC, you will receive this error.
It looks like you should be able to fix the problem by adding
WHERE INV_ID = #INV_ID
to ensure that only a single record is selected, i.e.:
SET #InvFindQTY = ( SELECT INV_QTY FROM OTH_INV_QTY_LOC WHERE INV_ID = #INV_ID)
I have the following Stored Procedure :
ALTER PROCEDURE [dbo].[ProcedureName]
#date NVARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #result nvarchar(500) -- this one should return string.
DECLARE #variable1 NVARCHAR(50)
set #variable1 = (SELECT COUNT(*) FROM dbo.Table1 WHERE column1 not in (select column1 from dbo.Table2))
DECLARE #variable2 NVARCHAR(50)
update dbo.Table1 set columnX = 1 where column1 not in (select column1 from dbo.Table2)
set #variable2 = ##ROWCOUNT
and so on... it continues like 200 rows of script with at least 10-12 variables
after that I want to get result like this
'Hello,' +
'Some Text here' +
#date +': ' +
'Explaining text for variable1- ' + #variable1 +
'Updated rows from variable2 - ' + #variable2 +
'some other select count - ' + #variable3 +
'some other update rowcount - '+ #variable4
......
till now i was able to get this with PRINT Statement, but can't take it to variable in my C# code which goes like this:
public void Execute_Click(object sender, EventArgs e)
{
if (MessageBox.Show("Are you sure you want to execute the program?", "Confirm Start", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.No)
{
string connectionString = GetConnectionString(usernamePicker.Text, passwordPicker.Text);
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand("dbo.ProcedureName", connection))
{
connection.Open();
cmd.CommandText = "dbo.ProcedureName";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#date", SqlDbType.VarChar).Value = dateTimePicker1.Text;
SqlParameter result = cmd.Parameters.Add("#result", SqlDbType.VarChar);
result.Direction = ParameterDirection.ReturnValue;
cmd.ExecuteScalar();
var resultout = (string)cmd.Parameters["#result"].Value;
connection.Close();
TextMessage.Text = dateTimePicker1.Text;
}
}
}
}
all i get for result is 0 or NULL or etc.
i tried to return value from SQL with PRINT, RETURN, SET, OUTPUT ....... but nothing seems to work. However fetching variable from C# to SQL seems like child-work. Any ideas?
If you want to return the concatenate string as output then at the end of the procedure just write select #result. Make sure that you have concatenated it before this statement.
This will return you the string which you can use in your c# code as a string.
Change your stored procedure to this:
ALTER PROCEDURE [dbo].[ProcedureName]
#date NVARCHAR(50),
#variable1 NVARCHAR(50) output,
#variable2 NVARCHAR(50) output
AS
BEGIN
SET NOCOUNT ON;
DECLARE #result nvarchar(500) -- this one should return string.
set #variable1 = (SELECT COUNT(*) FROM dbo.Table1 WHERE column1 not in (select column1 from dbo.Table2))
update dbo.Table1 set columnX = 1 where column1 not in (select column1 from dbo.Table2)
set #variable2 = ##ROWCOUNT
and modify your code like this:
SqlParameter result1 = cmd.Parameters.Add("#variable1", SqlDbType.VarChar);
result1.Direction = ParameterDirection.ReturnValue;
SqlParameter result2 = cmd.Parameters.Add("#variable2", SqlDbType.VarChar);
result2.Direction = ParameterDirection.ReturnValue;
ok lets say I did this procedure
ALTER PROCEDURE [dbo].[ProcedureName]
#date NVARCHAR(50),
#result nvarchar(500) output
AS
BEGIN
SET NOCOUNT ON;
DECLARE #variable1 NVARCHAR(50)
set #variable1 = (SELECT COUNT(*) FROM dbo.Table1 WHERE column1 not in (select column1 from Table2))
set #result = #variable1 + ' some text '
i want "#result" to be output text from procedure and get it with C#