Issue in executing parameterised query inside stored procedure - c#

I have stored procedure in which I'm executing a query. When I execute the query it returns multiple rows instead of one. But when I execute the same query without the store procedure it returns single row. Since I'm new to MySQL I'm facing issues in declaring variables inside stored procedures and using them.
I'm calling the stored procedure from C# code.
Stored procedure code(returns multiple values):
CREATE PROCEDURE `USP_UPDATE_BLACKLIST_RECORD_DETAIL`(
FILE_NAME varchar(100)
)
BEGIN
SET #FILE_NAME=null; SET #FILE_NAME = FILE_NAME;
SET #UPDATE_CODE = null; SET #ACTUAL_RECORD_COUNT = null;
/*Get the update code of the extracted file*/
SET #UPDATE_CODE = (SELECT count(UPDATE_CODE) FROM TX_BLACKLIST_FILE_DETAIL WHERE FILE_NAME = #FILE_NAME );
select #UPDATE_CODE;
END
Query without stored procedure(returns single value):
set #FILE_NAME=null;
set #FILE_NAME='TPCCH_ULEPL_20141112_164635.BLT';
set #UPDATE_CODE=null;
set #ACTUAL_RECORD_COUNT=null;
/*Get the update code of the extracted file*/
SET #UPDATE_CODE = (SELECT count(UPDATE_CODE) FROM TX_BLACKLIST_FILE_DETAIL WHERE FILE_NAME = #FILE_NAME );
select #UPDATE_CODE;
end

Related

Use only one petition to server instead multiple

I have a list of CheckBoxes:
List<CheckBox> checkBoxes = new List<CheckBox>();
I want to update it via a stored procedure, so I have:
private void btnSave_Click(object sender, EventArgs e)
{
SQLConnMgr db = new SQLConnMgr();
foreach (var c in checkBoxes)
{
db.ExeSQL($"exec test #CheckBoxName = {c.Name}, #CheckBoxValue = {c.Checked} ");
}
}
Stored procedure:
CREATE OR ALTER PROCEDURE test
-- Add the parameters for the stored procedure here
#CheckBoxName VARCHAR(255),
#CheckBoxValue BIT
AS
BEGIN
SET NOCOUNT ON;
-- Insert statements for procedure here
UPDATE MyTable SET #CheckBoxName = #CheckBoxValue
END
My question is: is there another way to do this? Like sending multiple petitions in the foreach statement instead of only one at a time?
UPDATE
So to be more clear every bool is a column so I need something like:
DECLARE #CurrentCheckboxName VARCHAR(255) = (SELECT
[CheckBoxName]
FROM #CheckBoxList)
UPDATE [m]
SET
#CurrentCheckboxName = [c].[CheckBoxValue]
FROM [RedMarkItems] [m]
JOIN #CheckBoxList [c] ON [c].[CheckBoxName] = #CurrentCheckboxName
but how can iterate on each checkboxName in my DECLARE?
Depending on the version of SQL Server you are using, you could use a TABLE parameter type for your stored proc and call it only once.
CREATE TYPE dbo.MyCheckBoxValues AS TABLE(
CheckBoxName VARCHAR(255) NOT NULL,
CheckBoxValue BIT NOT NULL )
Then you modify your stored proc to use the type.
CREATE OR ALTER PROCEDURE test
-- Add the parameters for the stored procedure here
#CheckBoxList MyCheckBoxValues READONLY
AS
BEGIN
SET NOCOUNT ON;
-- Insert statements for procedure here
UPDATE m SET CheckBoxValue=c.CheckBoxValue
FROM MyTable m
JOIN #CheckBoxList c ON c.CheckBoxName=m.CheckBoxName
END
You can also use Dynamic SQL in your stored proc. For Each checkboxValues :
DECLARE #Query nvarchar(max);
SET #Query = 'UPDATE Table SET ' + #CheckboxName + '='+ #CheckBoxValue;
exec sp_executeSql #Query
Then you only have to get the values in your code.
Something like this should do it.
StringBuilder builder = new StringBuilder();
builder.Append("DECLARE #MyCheckboxes MyCheckBoxValues; ");
foreach (Guid id in _equipmentToMerge)
{
builder.Append(String.Format("INSERT INTO #MyCheckboxes (CheckBoxName, CheckBoxValue) VALUES ('{0}',{1}); ", name, ischecked));
}
builder.Append("exec dbo.test #MyCheckboxes ");
I think there is a problem with your Update statement in your stored procedure. Could you change it thusly?
Update MyCheckBoxValues SET CheckBoxValue = #CheckBoxValue Where CheckBoxName = #CheckBoxName
I don't know why you want to complicate things. Use a single connection for the loop and I can't imagine that you could have a prohibitive number of check boxes on your form. If it is still too slow, get rid of entity framework or whatever orm you are using and try dealing with the server directly.

Dapper/SQL Server - get output from Stored Procedure containing Insert and Select statements

I just started learning Dapper in C# but I am having difficulty in executing stored procedures with two or more SQL Statements in one transaction.
How do you get the output parameter of a Stored Procedure that
contains both Insert and Select statements in C# using Dapper?
Here is my stored procedure:
ALTER PROCEDURE [dbo].[AddToFileDetailsAndGetPrimaryKey]
-- 1. declare input variables
#file_name NVARCHAR(100) = NULL,
-- 2. declare output variable
#file_details_pk UNIQUEIDENTIFIER OUTPUT
AS
-- 3. instantiate holder table
DECLARE #pk_holder TABLE
(
retrieved_pk UNIQUEIDENTIFIER
)
-- 4. insert into FileDetails
INSERT INTO dbo.FileDetails
(
file_name
)
OUTPUT INSERTED.file_details_pk INTO #pk_holder
VALUES
(
#file_name
);
-- 5. set FileDetails primary key to OUTPUT variable
SELECT #file_details_pk = retrieved_pk
FROM #pk_holder
Here is the code I'm using to execute the stored procedure:
using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(Configuration.GetConnectionString("TESTDB")))
{
List<FileDetails> fileList = new List<FileDetails>();
fileList.Add(new FileDetails { file_name = fileName});
Guid outputPrimaryKey;
connection.Execute("dbo.AddToFileDetailsAndGetPrimaryKey #file_name, #file_details_pk", fileList, outputPrimaryKey);
}
Is this the correct way to do it? Should I use connection.Execute or
connection.Query? I am also getting an error of "cannot convert from
System.Guid to System.Data.IDbTransaction in my outputPrimaryKey"
A. Dapper does not have a Query and Execute "combined" method, to my best knowledge.
B. However, since your stored procedure is a black box with input and output parameters, you can try this: (pseudo code below, not tested)
var p = new DynamicParameters();
p.Add("#file_name", "fileOne");
p.Add("#file_details_pk", dbType: DbType.Guid, direction: ParameterDirection.Output);
cnn.Execute("dbo.AddToFileDetailsAndGetPrimaryKey", p, commandType: CommandType.StoredProcedure);
Guid b = p.Get<Guid>("#file_details_pk");
From:
https://github.com/perliedman/dapper-dot-net
("stored procedures")
In general:
Dapper is built for speed.
Also. Dapper has limited functionality:
From
https://github.com/perliedman/dapper-dot-net
Dapper is a single file you can drop in to your project that will
extend your IDbConnection interface.
It provides 3 helpers:
See
Comparing QUERY and EXECUTE in Dapper
and
https://github.com/perliedman/dapper-dot-net/blob/master/Dapper%20NET40/SqlMapper.cs
PS..........
You seem to have a small bug in your "output" clause.....
You are pushing the file_name into the holding-table, not new value of the newly inserted PK.
-- 4. insert into FileDetails
INSERT INTO dbo.FileDetails
(
file_name
)
OUTPUT INSERTED.file_details_pk INTO #pk_holder
VALUES
(
#file_name /* << this looks wrong */
);

Stored procedure/query two variable comparison

I have created a stored procedure for SQL Server 2014.
There are two parameters: Name which is a user name and Hash which is password md5 hash. I check in the database if the md5 hashes are equal (first hash is from the program and the second one is already stored in the database).
If I just run a query (not a stored procedure) in the database (or in program using commandType.Text) - everything works and the user is being selected, but when I run the exact thing but using stored procedures, the SqlReader in C# has no elements returned, which most likely means that the conditions during those variable comparison were not met.
Maybe I am doing something wrong?
I also have about 10 other stored procedures for reading or/and writing to the database, everything works except this one.
Here is the procedure:
CREATE PROCEDURE GetHash
#Name nvarchar(50),
#Hash nvarchar(200)
AS
BEGIN
SET NOCOUNT ON;
SELECT Orders.orderId, Employee.name, Employee.surname
FROM Orders
LEFT JOIN Employee ON Orders.orderId = Employee.id
WHERE batchName = '#Name' AND productCode = '#Hash'
END
GO
Code part:
public Boolean VerifyPassword(string name, string password)
{
var paramsList = new List<SqlParameter> { new SqlParameter("#Name", name), new SqlParameter("#Hash", GetMd5Hash(password)) };
const string ProcedureName = "GetHash";
var ActiveUser = new DBController().GetFromDatabase(ProcedureName, "Login", "EJL15_DB", paramsList).ToList();
return ActiveUser.Count > 0;
}
And from Database Controller
private void SetCommandProperties(string procedureName, IEnumerable<SqlParameter> paramsList)
{
this.sqlCommand.CommandText = procedureName;
this.sqlCommand.CommandType = CommandType.StoredProcedure;
foreach (var curParam in paramsList)
this.sqlCommand.Parameters.Add(curParam);
this.sqlCommand.CommandTimeout = 15;
}
You don't need to quote the parameters in the stored procedure. Do this instead:
CREATE PROCEDURE GetHash
#Name nvarchar(50),
#Hash nvarchar(200)
AS
BEGIN
SET NOCOUNT ON;
SELECT Orders.orderId,
Employee.name,
Employee.surname
FROM Orders
LEFT JOIN Employee
ON Orders.orderId=Employee.id
WHERE batchName = #Name
AND productCode = #Hash
END
I just wonder, obviously your #Hash parameter passed to the stored
procedure is a user's password. But for some reason your WHERE clause
in the procedure goes like that:
"WHERE batchName='#Name' AND productCode='#Hash'"
Is there a chance your condition is incorrect? I guess it should be something like: Employee.password = #Hash
You should not put '' around your variables. Otherwise your comparison is totally wrong.

Passing comma delimited string to stored procedure?

I have this stored procedure:
ALTER PROCEDURE [dbo].[uspPages_HotelPrices_Lookup_Select]
#HotelCode nvarchar(100)
AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM tPages_HotelPrices_Lookup
WHERE HotelCode IN (SELECT * FROM DBO.ufSplit(#HotelCode, ','))
END
DBO.ufsplit splits a comma delimited string and returns a table of which each row containing each of the comma separated values.
I am passing a string to this stored procedure with the code below:
static void Main(string[] args)
{
HotelCodesTableAdapter hcTa = new HotelCodesTableAdapter();
DestinationMarketingEntity.HotelCodesDataTable hotelCodesDt = hcTa.GetData();
string hotelCodesString = "";
//Comma separating hotel codes and putting each word in '' to be passed to sql sproc as a list
for (int i = 0; i < hotelCodesDt.Count; i++)
{
hotelCodesString += hotelCodesDt.Rows[i].ItemArray.GetValue(0).ToString() + ",";
}
hotelCodesString = hotelCodesString.TrimEnd(',');
HiltonEEHotelPricesTableAdapter hEETa = new HiltonEEHotelPricesTableAdapter();
WorldWideFeedEntity.HiltonEEHotelPricesDataTable hEEDt= hEETa.GetData(hotelCodesString);
}
The last line is where the stored procedure is being called.
Essentially hotelCodesString will be similar to "1,2,3" but this is returning nothing form this stored procedure. But if I run the below:
select *
from tPages_HotelPrices_Lookup
where HotelCode IN
(
SELECT *
FROM DBO.ufSplit('1,2,3',',')
);
It gets back everything that I want. Am I missing something here? Why will it not return anything when passing from values with c#?
Don't do the split at all. Create a table valued parameter and pass this to your stored procedure. Then change your stored procedure to join to the table valued parameter.
Your sproc will end up looking like this:
CREATE PROCEDURE [dbo].[uspPages_HotelPrices_Lookup_Select]
#HotelCodes dbo.MyCodesTable READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM tPages_HotelPrices_Lookup a
INNER JOIN #HotelCodes b ON (a.ID = b.ID)
END
There are lots of good examples of using table values parameters on SO and the internet. A good method to get used to.
You can try doing the split in C# instead of at the db level.
string[] m_separators = new string[] { "," };
string[] m_stringarray = somestring.Split(m_separators, StringSplitOptions.RemoveEmptyEntries);
Or follow the examples on SO regarding passing an array to a stored proc. It is probably what you want to do anyway.

Get value output from SQL Server stored procedure into variable

This seems to be a simple question but nevertheless I haven't found an answer yet.
I have the following stored procedure
CREATE PROCEDURE [dbo].[AllocateId]
AS
BEGIN TRANSACTION
UPDATE TOP(1) IdReservation
SET IsAllocated = 1
OUTPUT DELETED.Id
WHERE IsAllocated = 0
COMMIT TRANSACTION
GO
It's been used in C# + EF code without a problem via ExecuteFunction of ObjectContext
ObjectResult<int> objectResult = ExecuteFunction<int>("AllocateId");
However when I try to call it directly from SQL script it doesn't seem to work
declare #Id int
EXEC #Id = [dbo].[AllocateId]
#Id is always 0. How do I get the value into #Id variable in sql script?
Procedure return value is different from result set(s) returned by that procedure. Your stored procedure returns a result set and does not return a return value (which ends up being null, which gets converted to 0 implicitly upon exiting the procedure).
To get the resultset your existing procedure retuns, you need insert ... exec:
declare #t table (id int);
insert into #t
exec [dbo].[AllocateId];
If you want to return a value as a return value as well, you should amend you stored procedure:
CREATE PROCEDURE [dbo].[AllocateId]
AS
BEGIN TRANSACTION
declare #id int;
UPDATE TOP(1) IdReservation
SET #id = Id, IsAllocated = 1
OUTPUT DELETED.Id
WHERE IsAllocated = 0
COMMIT TRANSACTION
return #id;
Then it will work in the way you describe in the question.

Categories

Resources