Get the value from Output parameter C# - sql

hi i'm try to create sp in sql with output value
this is the code
ALTER PROCEDURE [dbo].[usp_SelectHospital_IfExiste_Department]
#HospitalDepartmentID INT,
#IfExiste INT OUTPUT
AS
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
IF NOT EXISTS (SELECT c.DeptID FROM Clinic c WHERE DeptID=#HospitalDepartmentID )
BEGIN
SET #IfExiste=0
SELECT
[HospitalDepartmentID],
[NAME]
FROM
[dbo].[Hospital_Department]
WHERE
[HospitalDepartmentID] = #HospitalDepartmentID
END
ELSE
BEGIN
SET #IfExiste=1
SELECT
[HospitalDepartmentID],
[NAME]
FROM
[dbo].[Hospital_Department]
WHERE
[HospitalDepartmentID] = #HospitalDepartmentID
END
and the C# code
public static Hospital_Department GetDepartmentInfo(int ID,int OutIfExist)
{
SqlCommand cmd;
SqlDataReader dr;
Hospital_Department HD = new Hospital_Department();
using (cmd = new SqlCommand("usp_SelectHospital_IfExiste_Department", ProjectCon.GetCon()))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#HospitalDepartmentID", ID);
//cmd.Parameters.Add("#IfExiste",SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.Parameters.Add("#IfExiste",SqlDbType.Int);
cmd.Parameters["#IfExiste"].Direction = ParameterDirection.Output;
dr = cmd.ExecuteReader();
while (dr.Read())
{
HD.NAME = dr["NAME"].ToString();
HD.HospitalDepartmentID = Convert.ToInt32(dr["HospitalDepartmentID"]);
}
OutIfExist = Convert.ToInt32(cmd.Parameters["#IfExiste"].Value);
return HD;
}
}
when i try to get the output value is always null
and i run the stored procedure in sql Was run and return the value
so plz tell me what's wrong in my code
thx

Maybe this question has useful info:
According to, http://msdn.microsoft.com/en-us/library/ms971497, you must close the datareader before you process the output parameters.
Hope it helps.

Related

Is there a way to set a parameter from a stored procedure to a var query?

I'm working in a .net app specifically in a validation scripted in a stored procedure. This simple validation checks if there is already a policy with the same policy number that the user is trying to insert and throws an error message.
The problem that I'm facing is of the kind
Procedure or function 'pr_Policy_CheckPolicyNumber' expects parameter '#companyID', which was not supplied.
That's because I added a new field from the same PolicyBill table named (CompanyID).
My question is if it's there a way to set the #CompanyID value directly to the function and fix that error
The stored procedure is
CREATE OR ALTER PROCEDURE [dbo].[pr_Policy_CheckPolicyNumber]
(
#policyNumber VARCHAR(50) ,
#effectiveOn DATETIME ,
#companyID BIGINT
)
AS
IF ( ( SELECT COUNT(pb.policyBillID)
FROM PolicyBill pb
WHERE pb.policyNumber = #policyNumber
AND ( #effectiveOn >= pb.effectiveOn ) and (#effectiveOn <= pb.expiresOn )
AND pb.isActive = 1
AND pb.statusID = 56
AND pb.documentTypeID = 1
AND pb.companyID = #companyID
) > 0 )
BEGIN
PRINT N'The Policy already exists';
SELECT 1
END
ELSE
BEGIN
SELECT 0
END
and the Function is:
private bool CheckPolicyNumber()
{
var result = true;
var query = $"EXEC pr_Policy_CheckPolicyNumber '{txtPolicyNumber.Text}','{deEffectiveON.Date:yyyy/MM/dd}', '#companyID'";
var dt = AhkSqlHelper.ahkExecuteDataTable(query);
result = Convert.ToBoolean(Convert.ToInt16(dt.Rows[0][0].ToString()));
return result;
}
Any help would be appreciated.
Ad mentioned in the comment, the original code is fairly dangerous and you could be open to SQL injection attacks. The best solution is parameterize your command, something like this should do the trick:
using System.Data.SqlClient;
using System.Data;
string connString = "YourConnectionString";
string spName = "pr_Policy_CheckPolicyNumber";
private bool CheckPolicyNumber(string policyNumber, DateTime effectiveOn, long companyID)
{
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(spName, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter parameter1 = new SqlParameter("#policyNumber ", policyNumber);
cmd.Parameters.Add(parameter1);
SqlParameter parameter2 = new SqlParameter("#effectiveOn ", effectiveOn);
cmd.Parameters.Add(parameter2);
SqlParameter parameter3 = new SqlParameter("#companyID ", companyID);
cmd.Parameters.Add(parameter3);
var result = cmd.ExecuteScalar()
return (bool)result;
}
}
}

Insert a record if it does not exist in database and show a message to user if a record is already in database

I want to insert a record if it does not exist in our database .If the data to be inserted already exist in database then a messagebox should be displayed to user that the data that you want to insert is already in the database.
ALTER PROCEDURE sp_InsertRoles
(
#roleName varchar(50),
#roleStatus tinyint
)
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM tblRole WHERE roleName = #roleName and roleStatus=#roleStatus)
BEGIN
SELECT 'FALSE'
END
ELSE
BEGIN
INSERT INTO tblRole
VALUES(#roleName,#roleStatus)
SELECT 'TRUE'
END
END
string cs =
ConfigurationManager.ConnectionStrings["School_Management_System.Properties.
Settings.schoolManagementDBConnectionString"].ConnectionString;
SqlConnection con = new SqlConnection(cs);
SqlCommand cmd = new SqlCommand("sp_InsertRoles", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#roleName",txtRole.Text);
cmd.Parameters.AddWithValue("#roleStatus",ddlStatus.SelectedItem);
con.Open();//connection open
cmd.ExecuteNonQuery();
int count = Convert.ToInt32(cmd.ExecuteScalar());
if (count > 0)
{
MessageBox.Show("Role already exits...", "Failed",MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else if (count <= 0)
{
MessageBox.Show("Role inserted successfully...", "Success",MessageBoxButtons.OK, MessageBoxIcon.Information);
}
con.Close();
Use using blocks for you database objects. That will ensure they are closed and disposed even if there is an error. You will want to declare count outside of the using blocks so you can use it after the connection is closed. You don't want to show message boxes while a connection is open. Connections are precious resources and should be opened right before the .Execute... and closed as soon as possible.
Use the .Add method instead of .AddWithValue See http://www.dbdelta.com/addwithvalue-is-evil/
and
https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
and another one:
https://dba.stackexchange.com/questions/195937/addwithvalue-performance-and-plan-cache-implications
Here is another
https://andrevdm.blogspot.com/2010/12/parameterised-queriesdont-use.html
Since your stored procedure returns the strings True or False, I changed count to a boolean and adjusted tne If block.
private void UpdateDatabse()
{
string cs = ConfigurationManager.ConnectionStrings["School_Management_System.Properties.Settings.schoolManagementDBConnectionString"].ConnectionString;
bool count;
using (SqlConnection con = new SqlConnection(cs))
{
using (SqlCommand cmd = new SqlCommand("sp_InsertRoles", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#roleName",SqlDbType.VarChar, 50 ).Value = txtRole.Text;
cmd.Parameters.Add("#roleStatus",SqlDbType.TinyInt).Value = (int)ddlStatus.SelectedItem;
con.Open();
count = Convert.ToBoolean(cmd.ExecuteScalar());
}
}
if (count)
{
MessageBox.Show("Role inserted successfully...", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Role already exits...", "Failed", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}

Invalid column name when performing update

I have been trying to update data to database however i met this problem.I tried deleting the table and creating a new table yet the problem still persist.Below are the codes.Any help will be greatly appreciated
public int UpdateNOK(string wardClass, DateTime admissionDT, string nokFName, string nokLName, string nokNRIC, DateTime nokDOB, string nokGender, string nokNationality, string nokRelationship, int nokContactH, int nokContactHP, string nokEmail, string nokAddr1, string nokAddr2, string nokState, int nokZIP, string nokCountry, DateTime dischargeDT, string patientNRIC)
{
StringBuilder sqlStr = new StringBuilder();
int result = 0;
SqlCommand sqlCmd = new SqlCommand();
sqlStr.AppendLine("Update patientAdmission");
sqlStr.AppendLine("SET wardClass = #parawardClass,admissionDT = #paraadmissonDT, nokFName = #parapatientNokFname, nokLName = #parapatientNokLname,nokNRIC = #parapatientNokNRIC, nokDOB = #parapatientNOKDOB, nokGender = #parapatientNokGender, nokNationality = #parapatientNokNationality,");
sqlStr.AppendLine("nokRelationship = #parapatientNokRelationship,nokContactH = #parapatientNokContactH,nokContactHP = #parapatientNokContactHP, nokEmail = #parapatientNokEmail, nokAddr1 = #parapatientNokAddr1,nokAddr2 = #parapatientNokAddr2,nokState = #parapatientNokState, nokZIP = #parapatientNokZIP,");
sqlStr.AppendLine("nokCountry = #parapatientNokCountry, dischargeDT = #paradischargeDateTime");
sqlStr.AppendLine("WHERE patientNRIC = #parapatientNRIC");
try
{
SqlConnection myConn = new SqlConnection(DBConnect);
sqlCmd = new SqlCommand(sqlStr.ToString(), myConn);
sqlCmd.Parameters.AddWithValue("#parawardClass", wardClass);
sqlCmd.Parameters.AddWithValue("#paraadmissonDT", admissionDT);
sqlCmd.Parameters.AddWithValue("#parapatientNokFname", nokFName);
sqlCmd.Parameters.AddWithValue("#parapatientNokLname", nokLName);
sqlCmd.Parameters.AddWithValue("#parapatientNokNRIC", nokNRIC);
sqlCmd.Parameters.AddWithValue("#parapatientNOKDOB", nokDOB);
sqlCmd.Parameters.AddWithValue("#parapatientNokGender", nokGender);
sqlCmd.Parameters.AddWithValue("#parapatientNokNationality", nokNationality);
sqlCmd.Parameters.AddWithValue("#parapatientNokRelationship", nokRelationship);
sqlCmd.Parameters.AddWithValue("#parapatientNokContactH", nokContactH);
sqlCmd.Parameters.AddWithValue("#parapatientNokContactHP", nokContactHP);
sqlCmd.Parameters.AddWithValue("#parapatientNokEmail", nokEmail);
sqlCmd.Parameters.AddWithValue("#parapatientNokAddr1", nokAddr1);
sqlCmd.Parameters.AddWithValue("#parapatientNokAddr2", nokAddr2);
sqlCmd.Parameters.AddWithValue("#parapatientNokState", nokState);
sqlCmd.Parameters.AddWithValue("#parapatientNokZIP", nokZIP);
sqlCmd.Parameters.AddWithValue("#parapatientNokCountry", nokCountry);
sqlCmd.Parameters.AddWithValue("#paradischargeDateTime", dischargeDT);
sqlCmd.Parameters.AddWithValue("#parapatientNRIC", patientNRIC);
myConn.Open();
result = sqlCmd.ExecuteNonQuery();
myConn.Close();
Console.WriteLine(result);
}
catch (Exception ex)
{
logManager log = new logManager();
log.addLog("patientNOKDAO.UpdateNOK", sqlStr.ToString(), ex);
}
return result;
}
}
You should check table definition (sp_help) against your used columns in the table patientAdmission:
wardClass
admissionDT
nokFName
nokLName
nokNRIC
nokDOB
nokGender
nokNationality
nokRelationship
nokContactH
nokContactHP
nokEmail
nokAddr1
nokAddr2
nokState
nokZIP
nokCountry
dischargeDT
patientNRIC
If database default collation is a case-sensitive one, column names above must be exactly as defined in the table (case cannot be different).
One way to find the problem faster is to run SQL profiler and see the exact query against the database. Copy-paste it from there and run it into an Management Studio (SSMS) query file (use BEGIN TRAN .. ROLLBACK to ensure that nothing will actually be changed when you make it work). SSMS will try to indicate the exact column with the problem when clicking on the error.

SQL lock row,table on insert and select

I am trying to achieve some sort of lock on sql.
To explain what am i doing simple:
One table with Id int autoincrement as PK, and one field Data varchar(max) non-clustered IX
Now i have some C# code that simlpy checks if the item isn't in the db, makes an insert
The sql code that i am using behind is like:
INSERT INTO {0}.{1} WITH (TABLOCKX) VALUES(#data...)
and the select one is:
SELECT Id FROM {0}.{1} WITH (TABLOCKX) WHERE(Data = #data)
But i can see that there are items with the same value inserted multiple times
TABLOCK creates deadlocks, and i dont want to use unique index because its very slow.
Is there a way to achieve this with locking?
I'm not sure it is what you want, I hope that this reply is helpful.
private void test(string aConnectionString, string aData)
{
using (SqlConnection sqlConnection = new SqlConnection(aConnectionString))
{
sqlConnection.Open();
SqlCommand sqlCommand = sqlConnection.CreateCommand();
SqlTransaction sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted);
sqlCommand.Connection = sqlConnection;
sqlCommand.Transaction = sqlTransaction;
try
{
sqlCommand.CommandText = #"IF NOT EXISTS(SELECT Id FROM {0}.{1} WHERE Data = #Data)
BEGIN
INSERT INTO {0}.{1}
SELECT #Data
END";
sqlCommand.Parameters.Add("#Data", System.Data.SqlDbType.VarChar).Value = aData;
sqlTransaction.Commit();
}
catch (Exception ex)
{
sqlTransaction.Rollback();
}
}
}

Retrieve value of a table and using the value in stored procedure

I'm beginner in SQL Server 2012; I need to generate a product ID in a stored procedure, I generated part of the ID in C#, that part of ID includes Industrialist ID and I pass this to my stored procedure. In the stored procedure I need the last product of my Industrialist number and save in to as SQL variable on my stored procedure. How can I do this?
There are many ways to pass items between SQL and C#, you could use an output parameter where you will populate the parameter within the stored procedure.
string variableName;
using (var conn = new SqlConnection("**connection string**"))
using (var cmd = new SqlCommand("storedProcedureName", conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("inputParameter", inputParameter);
var outputParameter = new SqlParameter(){
ParameterName="ParameterName"
,Direction = ParameterDirection.Output
,SqlDbType = SqlDbType.VarChar
,DbType = DbType.VarChar
};
conn.Open();
try
{
cmd.ExecuteNonQuery();
variableName = string.Format("{0}", outputParameter.Value);
}
catch{}
finally
{
conn.Close();
}
}
You could return the value using something along the lines of RETURN #returnValue in your procedure, or you could return it within a table.
string variableName;
using (var conn = new SqlConnection("**connection string**"))
using (var cmd = new SqlCommand("storedProcedureName", conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("inputParameter", inputParameter);
conn.Open();
try
{
using (var dbReader = cmd.ExecuteReader())
{
if (dbReader.Read())
{
variableName = string.Format("{0}", dbReader["ColumnName"]);
}
}
}
catch{}
finally
{
conn.Close();
}
}
A generic example of a stored procedure which might work:
CREATE PROC [dbo].[storedProcedureName]
#InputParameter VARCHAR
,#OutputParameter VARCHAR OUTPUT
AS BEGIN
DECLARE #insertedId INT;
BEGIN TRANSACTION
INSERT INTO TableName (...Column Names...)
VALUES (... Values...)
SET #insertedId = SCOPE_IDENTITY()
COMMIT
SELECT #OutputParameter = ColumnName
FROM TableName
WHERE IdColumnName = #insertedId
END
EDIT: Possibly more relevant:
CREATE PROC [dbo].[storedProcedureName]
#IndustrialistId INT
,#OutputParameter VARCHAR OUTPUT -- This might be an int, but it's unclear what you want
AS BEGIN
DECLARE #productId INT;
SELECT #productId = MAX(ProductId)
FROM Products
WHERE IndustrialistId = #IndustrialistId;
SET #OutputParameter = CONVERT(VARCHAR,#IndustrialistId) + '-' + CONVERT(VARCHAR,#productId)
END
If you were to provide some code it might be easier for someone to give you a more tailored response. None of the above code has been syntax checked etc. so should be considered more pseudo code but hopefully it gives you something to work with.