I want to execute a stored procedure inside a Web Method. It is a select statement in the stored procedure. I tried with the following code. However, the result not successful. The result should return 1 but it is always returning -1. Does anyone have any idea? Please help.
Here is the web service .asmx code:
public class retrieveLoan : System.Web.Services.WebService
{
string constring = "Data Source=DIT-NB1260382;Initial Catalog=Experiment;Integrated Security=True";
SqlConnection myConn;
[WebMethod(Description="Simple Example")]
public int GetResult(int id, int age)
{
Int32 numberofRecords = 0;
System.Data.DataSet workDS = new System.Data.DataSet();
SqlCommand objCommand = default(SqlCommand);
//Create a command object
objCommand = new SqlCommand();
//prepare the command for retreiving
objCommand.CommandType = System.Data.CommandType.StoredProcedure;
objCommand.CommandText = "myprocedure2";
//open the connection
myConn = new SqlConnection(constring);
myConn.Open();
objCommand.Connection = myConn;
try
{
numberofRecords = (Int32)objCommand.ExecuteScalar();
return numberofRecords;
}
catch (Exception)
{
return -1;
}
finally
{
myConn.Close();
}
}
}
and my store procedure:
ALTER PROCEDURE [dbo].[myprocedure2]
(
#puserid int,
#page int
)
AS
BEGIN
select * from userdet where userid = #puserid and age = #page
END
I believe that executing this stored procedure without parameters would return an exception.
First of all, for you to see the Exception, in the catch declaration, you should try and declare the Exception explicitly, like this:
try
{
numberofRecords = (Int32)objCommand.ExecuteScalar();
return numberofRecords;
}
catch (Exception ex)
{
//here you can enter into debug mode and see the exception "ex"
return -1;
}
finally
{
myConn.Close();
}
When you see the exception, you can quickly solve the problem.
Next, you should add the parameters as NULL into your stored procedure (so they can accept null values), OR, if you do not, you must add these parameter in C# code, and send them some values.
Also, i would like to point the fact that if you want to retrieve a COUNT, you should modify your stored procedure as following:
ALTER PROCEDURE [dbo].[myprocedure2] ( #puserid int, #page int )
AS
BEGIN
select COUNT(userid) from userdet where userid = #puserid and age = #page
END
Hope this solves your issues here.
You're not providing a lot of info, so hard to answer, but here's a way forward:
Change catch (Exception) into catch (Exception ex), then see what that exception contains, either by returning it, or by analyzing it in debug mode.
If you publish your project in debug mode, you can connect to it and debug it using Tools > Attach to Process and connect to the process called w3wp.exe (if there are more than one of them, look for the one with the correct version of .Net under the Type-column).
Your query is "select * from userdet". What ExecuteScalar() does is pick the first cell value. Now you are type casting this to int. if your first cell value is a string type or some other type. you will definitely receive a error. And that will return -1. Please define the column name in your select query or count like this "select count(*) from userdet". Check ur query.
Related
I have the following code to be executed and I want to get the value of #synchronization_version from c#. Does any one know how this could be handled?
DECLARE #synchronization_version BIGINT
SET #synchronization_version = CHANGE_TRACKING_CURRENT_VERSION();
The most direct way is to use SqlCommand.ExecuteScalar. See this article: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar(v=vs.110).aspx .
Your SQL query would look like this:
SELECT Convert(BigInt,CHANGE_TRACKING_CURRENT_VERSION());
I modified the MSDN code as follows. This should work:
public static Int64 GetSynchronizationVersion(string connString)
{
Int64 synchronizationVersion = 0;
string sql =
"SELECT Convert(BigInt,CHANGE_TRACKING_CURRENT_VERSION());";
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
//This query has no parameters.
try
{
conn.Open();
synchronizationVersion = (Int64)cmd.ExecuteScalar();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
return synchronizationVersion;
}
This operation is called ExecuteScalar because it returns a single value (a scalar) rather than a set of rows.
Wrap it in a procedure like
create procedure Sp_getdata
as
begin
DECLARE #synchronization_version BIGINT OUTPUT
SET #synchronization_version = CHANGE_TRACKING_CURRENT_VERSION();
SELECT #synchronization_version;
end
Call the procedure from C#
SqlParameter outData = new SqlParameter("#synchronization_version", SqlDbType.BIGINT){ Direction = ParameterDirection.Output };
cmd.ExecuteScalar();
Then just read the value of output parameter
long result = outData.Value;
Say I have this stored procedure that I have no control over (and no access to the third party db).
How do I know if it worked?
BEGIN
Update USR
Set usr_psswrd = #NewPassword
where
usr_usrnme = #UserName and usr_psswrd = #OldPassword
END
I know how to get rows when there's a select statement in a stored procedure and read those rows but I have no idea how to check if this stored procedure worked or not.
This is what I'm doing so far that doesn't work. The stored procedure works because the password does change I just don't know what to do after the fact.
using (SqlConnection connection = new SqlConnection(connectionString))
{
// Create the command and set its properties.
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = "USP_ChangePassword";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#UserName", SqlDbType.VarChar).Value = email;
command.Parameters.Add("#OldPassword", SqlDbType.VarChar).Value = oldPW;
command.Parameters.Add("#NewPassword", SqlDbType.VarChar).Value = newPW;
try
{
// Open the connection and execute the reader.
connection.Open();
command.ExecuteNonQuery();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
success = true;
}
reader.Close();
}
catch (SqlException ex)
{
System.Diagnostics.Debug.Write("SqlException Error " + ex.Number + ": " + ex.Message);
}
catch (InvalidOperationException ex)
{
System.Diagnostics.Debug.Write("Invalid Op Error: " + ex.Message);
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write("Error: " + ex.Message);
}
finally
{
connection.Close();
}
}
IN the documentation about ExecuteNonQuery you could find
> Return Value
> Type: System.Int32
> The number of rows affected.
So you could change your code to
try
{
// Open the connection and execute the reader.
connection.Open();
int rowsUpdated = command.ExecuteNonQuery();
if(rowsUpdated > 0)
{
success = true;
}
}
This is the normal behavior of ExecuteNonQuery, but check if your stored procedure contains the statements
SET NOCOUNT ON
if you have this line, then ExecuteNonQuery cannot return the number of rows affected and you get always a -1 as return value. If you cannot change that stored procedure, then you are in trouble.
The only workaround that comes to mind is to get back the user data with a SELECT query and check against the inserted data (a very uncomfortable situation)
If you check the doco for the ExecuteNonQuery() method you'll see it returns an int, specifically:
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. For all other types of statements, the return value is -1. If a rollback occurs, the return value is also -1.
Therefore if you execute the method call and it returns a 1 then it is safe to assume that your field has been updated successfully.
This means you should also remove the SqlDataReader reader = command.ExecuteReader(); line, and add a return value check something like:
var success = command.ExecuteNonQuery() == 1;
(that's a compact way of doing it, you could split it out into multiple lines).
How would I take info stored in a Select method and transfer it to a string? I'm trying to get the max value from the match_id column and get its value from command.CommandText into the matchCode string. Where would I go from here?
string connectString = "Server=myServer;Database=myDB;Uid=myUser;Pwd=myPass;";
string matchCode = "";
MySqlConnection connect = new MySqlConnection(connectString);
MySqlCommand command = connect.CreateCommand();
command.CommandText = "SELECT MAX(VAL(match_id)) FROM `data`";
try
{
connect.Open();
command.ExecuteNonQuery();
matchCode = "??";
connect.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
I'm new to C#, as it's like my fourth day trying it out. Thanks for the help!
The ExecuteNonQuery() method is for INSERT/UPDATE/DELETE queries. If you're just getting a single value back, use ExecuteScalar(). If you're getting a whole result set back, use ExecuteReader() or Fill() a DataSet object.
Also, there are some things that are idiomatic to C# that you should be doing:
public int GetMatchCode()
{
//this could be loaded from config file or other source
string connectString = "Server=myServer;Database=myDB;Uid=myUser;Pwd=myPass;";
string sql = "SELECT MAX(VAL(match_id)) FROM `data`";
using (var connect = new MySqlConnection(connectString))
using (var command = new MySqlCommand(sql, connect))
{
connect.Open();
var result = command.ExecuteScalar();
if (result == DBNull.Value)
{
//what you do here depends on your application
// if it's impossible for the query to return NULL, you can even skip this
}
return (int)result;
}
}
Some of the changes need explanation:
I don't ever call .Close(). The using block takes care of that for me, even if an exception was thrown. The old code would have left the connection hanging if an exception occured.
.Net developers tend to believe in very small methods. More than that, this method ought to be part of a class that has nothing but other simple public data access methods and maybe a few private helper methods or properties for abstracting common code in the class.
There is no exception handling code here. If you have small methods that are part of a generic database access class, exception handling should be at higher level, where you are better positioned to make decisions about how to proceed.
I am trying to run a stored procedure returning a single integer value and I can't figure out where its going wrong. From what I've read the following should work but is not and I can't see where I'm going wrong.
Here is my stored procedure:
ALTER PROCEDURE [dbo].[getDDNTempID]
AS
BEGIN
declare #tempID int
select top 1 #tempID = tempID from tblDDNHdr order by tempID asc
if #tempID is null
return 0
else
return #tempID
END
Here is the code where I try to get the return value:
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["test"].ConnectionString))
{
SqlCommand cmd = new SqlCommand("getDDNTempID", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection.Open();
Int32 tempID = (Int32)cmd.ExecuteScalar();
if (tempID == 0) { tempID = -1; }
return tempID;
}
When this procedure is called I get a NullReferenceException and the line giving the error is:
Int32 tempID = (Int32)cmd.ExecuteScalar();
I would appreciate any guidance you guys could give.
Thanks
The return function in SQL Server is specifically to return completion codes to the calling function. As such, the values available to be returned are limited. What you need to do instead is to SELECT #tempID and treat it as a result set.
ExecuteScalar returns the value of the first column of the first row of the results. Your stored procedure does not return a result set.
Add a parameter to the SqlCommand.Parameters collection and set the Direction to ReturnValue. It will receive the return value from the stored procedure.
Please note that the return value is intended only for returning a status. You should use an OUTPUT parameter to return #TempId.
doubles quotes dont work so you have to type 'some value' to actually do variable comparisons when doing direct execution of SQL statements.
Problem is that now when I execute the SQL statement from ASP.NET code I dont seem to be getting any readings...I am not even getting errors :S....
I HAVE tried executing the SQL statement on its own, and it does work.
public static string testExi(string localIncidentNum)
{
try
{
string query = "SELECT TOP 1 UniqueColID From DBNAME WHERE LocalIncidentNum = #localIncidentNum ORDER BY [version] DESC";
DataTable dt = new DataTable();
SqlConnection connection = new SqlConnection(connectionStr);
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("#localIncidentNum", localIncidentNum);
connection.Open();
SqlDataAdapter adp = new SqlDataAdapter(command);
adp.Fill(dt);
connection.Close();
command.Dispose();
connection.Dispose();
if (dt.Rows.Count != 0)
{
string UniqueColID = dt.Rows[0]["UniqueColID"].ToString();
return UniqueColID;
}
else
{
return null;
}
string some = dt.Rows[0]["UniqueColID"].ToString();
return some;
}
catch (Exception err)
{
Global.tmpmsg = " Updating follow up was not successful. " + err.ToString();
return null;
}
}
If I hardcode an incident value in the SELECT statement it works but if I hardcode the incident value in .addwithvalue, it doesn't work.
command.Parameters.AddWithValue("#localIncidentNum", "12-023696");
Double check your sql statement:
SELECT TOP 1 UniqueColID From WHERE LocalIncidentNum = #localIncidentNum ORDER BY [version] DESC
From Where?
Edit
In observance of your change, best to always be as accurate as possible when describing your problem. Leaving out something like the table name of a sql statement is very misleading.
Perhaps add a datatype to your command parameter. I believe that you are not getting anything because it may be timing out on the command.
command.Parameters.AddWithValue("#localIncidentNum", localIncidentNum);
command.Parameters[0].SqlDbType = SqlDbType.VarChar;
I found a similar problem here, also using Varchar:
AddWithValue without DBType causing queries to run slowly
I solved it. The problem was that I (for some reason) needed to put the full path of the table before the table name in sql code when executing it from C sharp file:
SELECT TOP 2 [DB name].[dbo]. [table name]