I have a simple SQL Server stored procedure:
ALTER PROCEDURE GetRowCount
(
#count int=0 OUTPUT
)
AS
Select * from Emp where age>30;
SET #count=##ROWCOUNT;
RETURN
I am trying to access the output parameter in the following C# code:
SqlConnection con = new SqlConnection();
con.ConnectionString = "Data Source=localhost\\SQLEXPRESS;Initial Catalog=answers;Integrated Security=True";
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "GetRowCount";
cmd.CommandType=CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#count", SqlDbType.Int));
cmd.Parameters["#count"].Direction = ParameterDirection.Output;
con.Open();
SqlDataReader reader=cmd.ExecuteReader();
int ans = (int)cmd.Parameters["#count"].Value;
Console.WriteLine(ans);
But on running the code, a NullReferenceException is being thrown at the second last line of the code. Where am I going wrong? Thanks in advance!
P.S. I am new to SQL Procedures, so I referred this article.
I'd suggest you put your SqlConnection and SqlCommand into using blocks so that their proper disposal is guaranteed.
Also, if I'm not mistaken, the output parameters are only available after you've completely read the resulting data set that's being returned.
Since you don't seem to need that at all - why not just use .ExecuteNonQuery() instead? Does that fix the problem?
using (SqlConnection con = new SqlConnection("Data Source=localhost\\SQLEXPRESS;Initial Catalog=answers;Integrated Security=True"))
using (SqlCommand cmd = new SqlCommand("dbo.GetRowCount", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#count", SqlDbType.Int));
cmd.Parameters["#count"].Direction = ParameterDirection.Output;
con.Open();
cmd.ExecuteNonQuery(); // *** since you don't need the returned data - just call ExecuteNonQuery
int ans = (int)cmd.Parameters["#count"].Value;
con.Close();
Console.WriteLine(ans);
}
Also : since it seems you're only really interested in the row count - why not simplify your stored procedure to something like this:
ALTER PROCEDURE GetRowCount
AS
SELECT COUNT(*) FROM Emp WHERE age > 30;
and then use this snippet in your C# code:
con.Open();
object result = cmd.ExecuteScalar();
if(result != null)
{
int ans = Convert.ToInt32(result);
}
con.Close();
you have to specify that it is a stored procedure not a query
cmd.CommandType = CommandType.StoredProcedure;
Just use ExecuteNonQuery , you can't use ExecuteReader with out parameter in this case
cmd.ExecuteNonQuery();
Or if you want try with ExecuteScalar and ReturnValue
You should add
cmd.CommandType = CommandType.StoredProcedure
before calling it
I find the problem, its the connection string.
But now, in the code:
usuary = (string)cmd.Parameters["#USUARIO"].Value;
password = (string)cmd.Parameters["#CLAVE"].Value;
the compiler infomrs thats values are null...
Related
I am quite new to SQLCLR stored procedures. In my example I have two stored procedures, one without a parameter and one with a input parameter. Both target the same tables.
The one without the parameter is working fine and returns all rows in the result. But the one with an input parameter targeting the same tables is not returning any rows even though I am not receiving any errors. The input parameter in the .NET code is set as SqlString and in the database is NVARCHAR(50).
This is how my C# code looks:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void AirlineSqlStoredProcedure (SqlString strAirline)
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Context Connection=true";
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "SELECT dbo.tblAirline.AirlineName, dbo.tblAircraft.AircraftUnits, dbo.tblAircraft.Manufacturer, dbo.tblAircraft.AircraftModel FROM dbo.tblAircraft INNER JOIN dbo.tblAirline ON dbo.tblAircraft.AirlineID = dbo.tblAirline.AirlineID WHERE AirlineName = '#strAirline' ORDER BY dbo.tblAircraft.AircraftUnits DESC";
SqlParameter paramAge = new SqlParameter();
paramAge.Value = strAirline;
paramAge.Direction = ParameterDirection.Input;
paramAge.SqlDbType = SqlDbType.NVarChar;
paramAge.ParameterName = "#strAirline";
cmd.Parameters.Add(paramAge);
SqlDataReader sqldr = cmd.ExecuteReader();
SqlContext.Pipe.Send(sqldr);
sqldr.Close();
conn.Close();
}
[Microsoft.SqlServer.Server.SqlProcedure]
public static void AirlineAircraftStoredProcedure()
{
//It returns rows from Roles table
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Context Connection=true";
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT dbo.tblAirline.AirlineName, dbo.tblAircraft.AircraftUnits, dbo.tblAircraft.Manufacturer, dbo.tblAircraft.AircraftModel FROM dbo.tblAircraft INNER JOIN dbo.tblAirline ON dbo.tblAircraft.AirlineID = dbo.tblAirline.AirlineID ORDER BY dbo.tblAircraft.AircraftUnits DESC";
conn.Open();
SqlDataReader sqldr = cmd.ExecuteReader();
SqlContext.Pipe.Send(sqldr);
sqldr.Close();
conn.Close();
}
}
And when I execute the stored procedure I get empty rows:
USE [TravelSight]
GO
DECLARE #return_value Int
EXEC #return_value = [dbo].[AirlineSqlStoredProcedure]
#strAirline = N'American Airlines'
SELECT #return_value as 'Return Value'
GO
(0 row(s) affected)
(1 row(s) affected)
Also, for the input parameter I put an N before the string.
When running the stored procedure AirlineAircraftStoredProcedure targeting the same tables, I am getting all the rows back:
USE [TravelSight]
GO
DECLARE #return_value Int
EXEC #return_value = [dbo].[AirlineAircraftStoredProcedure]
SELECT #return_value as 'Return Value'
GO
(8 row(s) affected)
(1 row(s) affected)
What have I done wrong here?
Two (maybe 3) problems:
paramAge.Value = strAirline; should be:
paramAge.Value = strAirline.Value;
Notice the use of the .Value property.
WHERE AirlineName = '#strAirline' (within cmd.CommandText = "... ) should be:
WHERE AirlineName = #strAirline
Notice that the single-quotes were removed in the query text. You only use single-quotes for literals and not parameters / variables.
Replace the following 5 lines:
SqlParameter paramAge = new SqlParameter();
paramAge.Value = strAirline;
paramAge.Direction = ParameterDirection.Input;
paramAge.SqlDbType = SqlDbType.NVarChar;
paramAge.ParameterName = "#strAirline";
with:
SqlParameter paramAge = new SqlParameter("#strAirline", SqlDbType.NVarChar, 50);
paramAge.Direction = ParameterDirection.Input; // optional as it is the default
paramAge.Value = strAirline.Value;
Please note that the "size" parameter was set in the call to new SqlParameter(). It is important to always specify max string lengths.
With the technical problem out of the way, there are two larger issues to address:
Why is this being done in SQLCLR in the first place? Nothing specific to .NET is being done. Based solely on the code posted in the Question, this would be much better off as a regular T-SQL Stored Procedure.
If it must remain in SQLCLR, then you really need to wrap the disposable objects in using() constructs, namely: SqlConnection, SqlCommand, and SqlDataReader. For example:
using (SqlConnection conn = new SqlConnection("Context Connection=true"))
{
using (SqlCommand cmd = conn.CreateCommand())
{
...
}
}
and then you do not need the following two lines:
sqldr.Close();
conn.Close();
as they will be called implicitly by the call to each of their Dispose() methods.
I am trying to get the stand output in c# returned from oracle stored procedure. dbms_output.put_line('Hello Word')
The c# code i am using is
using (OracleConnection con = new OracleConnection())
{
con.ConnectionString = My_connection_string;
con.Open();
OracleCommand cmd = new OracleCommand("tmp_test", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.BindByName = true;
var result = cmd.ExecuteScalar();
}
The oracle stored procedure code is
create or replace procedure tmp_test as
v_count integer;
begin
dbms_output.put_line('Hello Word');
end;
The stored procedure execute successfully but I can't get the Hello Word back.
After some struggle i have managed to find the answer and decided to post that might help other.
using (OracleConnection con = new OracleConnection())
{
con.ConnectionString = My_connection_string;
con.Open();
OracleCommand cmd = new OracleCommand("tmp_test", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.BindByName = true;
var result = cmd.ExecuteScalar();
//it is included dbms_output
cmd.CommandText = "begin dbms_output.enable (1000); end;";
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
string out_string;
int status = 0;
cmd.CommandText = "BEGIN DBMS_OUTPUT.GET_LINE (:out_string, :status); END;";
cmd.CommandType = CommandType.Text;
cmd.Parameters.Clear();
cmd.Parameters.Add("out_string", OracleType.VarChar, 32000);
cmd.Parameters.Add("status", OracleType.Double);
cmd.Parameters[0].Direction = System.Data.ParameterDirection.Output;
cmd.Parameters[1].Direction = System.Data.ParameterDirection.Output;
cmd.ExecuteNonQuery();
out_string = cmd.Parameters[0].Value.ToString();
status = int.Parse(cmd.Parameters[1].Value.ToString());
}
Here's a link to a the documentation for DBMS_OUTPUT package in Oracle - DBMS_OUTPUT
It specifically states that it's used for debugging Oracle Stored Procedures and that this is in essence a debug buffer that you need to actively poll use GET_LINES in order to see the output.
Function in PL/SQL should be something like this:
create or replace function tmp_test as
begin
RETURN 'Hello World';
end;
using this coding,while i give fruitId ,i need to retrieve fruitname,using this it shows some error..any one help...
string constring = ConfigurationManager.ConnectionStrings["conn"].ConnectionString;
using (SqlConnection con = new SqlConnection(constring))
{
using (SqlCommand cmd = new SqlCommand("savefruit11", con))
{
con.Open();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#FruitsId", int.Parse(TextBox3.Text.Trim()));
cmd.Parameters.Add("#Fruitsname", SqlDbType.VarChar, 50);
cmd.Parameters["#Fruitsname"].Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
con.Close();
TextBox4.Text = "Fruit Name:"+cmd.Parameters["#FruitName"].Value.ToString();
}
}
Store procedure for the above code.
use[FruitsDB]
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create PROCEDURE [dbo].[savefruit11]
#FruitId INT,
#FruitName VARCHAR(50) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT #FruitName = Fruitsname
FROM Fruits1
WHERE FruitsId = #FruitId
END
cmd.Parameters.Add("#Fruitsname", SqlDbType.VarChar, 50);
cmd.Parameters["#Fruitsname"].Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
con.Close();
TextBox4.Text = "Fruit Name:"+cmd.Parameters["#FruitName"].Value.ToString();
Your parameter is called #Fruitsname, but you get it back with #FruitName. You have an additional s in the first version. Make them consistent by changing the first #FruitsName to #FruitName which will match what you have in the stored procedure.
Or, as Henk suggested in the comments create a const string to contain your parameter name so that it is consistent across all usages.
Use cmd.ExecuteQuery or cmd.ExecuteScalar
//To Execute SELECT Statement
ExecuteQuery()
//To Execute Other Than Select Statement(means to Execute INSERT/UPDATE/DELETE)
ExecuteNonQuery()
with your udpate
s is missing in parameter name in stored procedure
Use the following example way
using (SqlConnection connection = new SqlConnection())
{
string connectionStringName = this.DataWorkspace.AdventureWorksData.Details.Name;
connection.ConnectionString =
ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
string procedure = "HumanResources.uspUpdateEmployeePersonalInfo";
using (SqlCommand command = new SqlCommand(procedure, connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(
new SqlParameter("#EmployeeID", entity.EmployeeID));
command.Parameters.Add(
new SqlParameter("#NationalIDNumber", entity.NationalIDNumber));
command.Parameters.Add(
new SqlParameter("#BirthDate", entity.BirthDate));
command.Parameters.Add(
new SqlParameter("#MaritalStatus", entity.MaritalStatus));
command.Parameters.Add(
new SqlParameter("#Gender", entity.Gender));
connection.Open();
command.ExecuteNonQuery();
}
}
reference from MSDN
http://msdn.microsoft.com/en-us/library/jj635144.aspx
I am getting following error when calling a stored procedure in SQL Server from C#:
Line 1: Incorrect syntax near 'spGet_Data'.
Here is my code:
public string GetData (string destinationFile)
{
string conectionString = "uid=One_User;pwd=One_Password;database=One_Database;server=One_Server";
SqlConnection con = new SqlConnection(conectionString);
SqlCommand sqlCmd = new SqlCommand();
string returnValue = string.Empty;
string procedureName = "spGet_Data";
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd = new SqlCommand(procedureName, con);
sqlCmd.Parameters.AddWithValue("#FileName", destinationFile);
con.Open();
var returnParameter = sqlCmd.Parameters.Add("#ret", SqlDbType.VarChar);
returnParameter.Direction = ParameterDirection.ReturnValue;
sqlCmd.ExecuteNonQuery();
returnValue = returnParameter.Value.ToString();
con.Close();
return returnValue;
}
Procedure itself returning data properly, I checked connection it is in Open state.
What else it can be?
Thank you.
The problem lies in the fact that you create the command two times.
After the first initialization you set correctly the CommandType to StoredProcedure, but once again you created the command and this time you forgot to set the CommandType
Just remove the first initialization, leave only the second one and move the CommandType setting after the initialization
SqlConnection con = new SqlConnection(conectionString);
string returnValue = string.Empty;
string procedureName = "spGet_Data";
SqlCommand sqlCmd = new SqlCommand(procedureName, con);
sqlCmd.CommandType = CommandType.StoredProcedure;
You create a SqlCommand object, then set it's CommandType property, then overwrite it by calling new on your command object again. Written out correctly, your code should look like this:
public string GetData (string destinationFile)
{
string conectionString = "uid=One_User;pwd=One_Password;database=One_Database;server=One_Server";
SqlConnection con = new SqlConnection(connectionString);
SqlCommand sqlCmd = new SqlCommand(procedureName, con);
sqlCmd.CommandType = CommandType.StoredProcedure;
string returnValue = string.Empty;
string procedureName = "spGet_Data";
sqlCmd.Parameters.AddWithValue("#FileName", destinationFile);
con.Open();
var returnParameter = sqlCmd.Parameters.Add("#ret", SqlDbType.VarChar);
returnParameter.Direction = ParameterDirection.ReturnValue;
sqlCmd.ExecuteNonQuery();
returnValue = returnParameter.Value.ToString();
con.Close();
return returnValue;
}
Also, I would highly suggest that you surround your SqlConnection and SqlCommand objects with the Using Statement. Much like this:
public string GetData (string destinationFile)
{
using (SqlConnection con = new SqlConnection(connectionString))
{
using (SqlCommand sqlCmd = new SqlCommand(procedureName, con))
{
}
}
}
The benefit of doing it this way is cleaner code and since your command and connection objects implement IDisposable, they will be handled by GC once they fall out of scope.
By the way, you have 'conectionString' misspelled; I fixed it in my code examples.
Whoops. This is being done, albeit incorrectly. See the other answer.
See SqlCommand.CommandType. You need to tell it to be treated as an sproc call. E.g.
sqlCmd.CommandType = CommandType.StoredProcedure;
Otherwise it results in an invalid SQL statement (i.e. running spGet_Data verbatim in an SSMS query should produce a similar messages).
I've been writing a lot of web services with SQL inserts based on a stored procedure, and I haven't really worked with any SELECTS.
The one SELECT I have in mind is very simple.
SELECT COUNT(AD_SID) As ReturnCount FROM AD_Authorization
WHERE AD_SID = #userSID
However, I can't figure out based on my current INSERT code how to make that into a SELECT and return the value of ReturnCount... Can you help? Here is my INSERT code:
string ConnString = "Data Source=Removed";
string SqlString = "spInsertProgress";
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("attachment_guid", smGuid.ToString());
cmd.Parameters.AddWithValue("attachment_percentcomplete", fileProgress);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
}
Here is where you are going wrong:
cmd.ExecuteNonQuery();
You are executing a query.
You need to ExecuteReader or ExecuteScalar instead. ExecuteReader is used for a result set (several rows/columns), ExecuteScalar when the query returns a single result (it returns object, so the result needs to be cast to the correct type).
var result = (int)cmd.ExecuteScalar();
The results variable will now hold a OledbDataReader or a value with the results of the SELECT. You can iterate over the results (for a reader), or the scalar value (for a scalar).
Since you are only after a single value, you can use cmd.ExecuteScalar();
A complete example is as follows:
string ConnString = "Data Source=Removed";
string userSid = "SomeSid";
string SqlString = "SELECT COUNT(AD_SID) As ReturnCount FROM AD_Authorization WHERE AD_SID = #userSID;";
int returnCount = 0;
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#userSID", userSid);
conn.Open();
returnCount = Convert.ToInt32(cmd.ExecuteScalar());
}
}
If you wanted to return MULTIPLE rows, you can use the ExecuteReader() method. This returns an IDataReader via which you can enumerate the result set row by row.
You need to use ExecuteScalar instead of ExecuteNonQuery:
String query = "SELECT COUNT(AD_SID) As ReturnCount FROM AD_Authorization WHERE AD_SID = #userSID ";
using (OleDbConnection conn = new OleDbConnection(ConnString)) {
using (OleDbCommand cmd = new OleDbCommand(query, conn))
{
cmd.Parameters.AddWithValue("userSID", userSID.ToString());
conn.Open();
int returnCount = (Int32) cmd.ExecuteScalar();
conn.Close();
}
}
cmd.executescalar will return a single value, such as your count.
You would use cmd.executereader when you are returning a list of records