I'm trying to execute a SQL request in C# to know if a user is already registered on my data base. To do that, I'm using the following source code :
public bool pseudoDispo(string pseudo)
{
// Ouverture de la connexion SQL
this.OpenConnection();
// Création d'une commande SQL en fonction de l'objet connection
MySqlCommand cmd = this.connection.CreateCommand();
cmd.CommandText = "SELECT COUNT(*) FROM `user` WHERE `pseudo` = '" + pseudo + "'";
int test = cmd.ExecuteNonQuery();
MessageBox.Show(test.ToString());
// Exécution de la commande SQL
if (cmd.ExecuteNonQuery() == 1)
{
this.connection.Close();
MessageBox.Show("Registered");
return true;
}
else
{
this.connection.Close();
MessageBox.Show("Not Registered");
return false;
}
}
But the problem is that MySqlCommand.ExecuteNonQuery() always returns -1 and I don't know why. My request seems work because it returns me the good result (1 if registered, 0 if not) on phpmyadmin.
Is there anyone to help me and explain me what I'm doing wrong please?
Thanks!
Edit: I've been trying to do my function on another way by using ExecuteScalar() but now I got some troubles with it because it always returns me 0. I clearly do not understand something but I don't even know what... Can I get more informations about ExecuteScalar() and that kind of functions?
I tried to cast it into a string, and it seems that cmd requests an Int64. So I updated my code like that, but it still doesn't work. I'm pretty depressed with my lack of knowledge but anyway, here is the code :
public int pseudoDispo(string pseudo)
{
Int64 dispo_pseudo = 0;
string sql = "SELECT COUNT(*) FROM `user` WHERE `pseudo` = '[pseudo] = ?' ";
MySqlCommand cmd = new MySqlCommand(sql);
try
{
this.OpenConnection();
OleDbCommand dbcommand = new OleDbCommand(sql);
dbcommand.Parameters.AddWithValue("#p1", pseudo);
dbcommand.CommandType = CommandType.Text;
dispo_pseudo = (Int64)dbcommand.ExecuteScalar();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return (int)dispo_pseudo;
}
You're calling ExecuteNonQuery, despite trying to execute... a query. You should be using ExecuteScalar - or ExecuteQuery and check whether there are any results.
ExecuteNonQuery is specifically for insert/delete/update SQL statements, and the number returned is the number of rows affected.
From the documentation of IDbCommand.ExecuteNonQuery:
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. For all other types of statements, the return value is -1.
(As an aside, you should almost certainly be creating a new connection each time, and use using statements for all the disposable object you're using, such as MySqlCommand.)
As mentioned already, you are trying to get results out of a Query. ExecuteNonQuery will only work for sql statements that do not return results.
Try something like this:
string strResult;
SqlDataReader sqlResult = cmd.ExecuteReader();
while (sqlResult.Read())
{
strResult = result[0].ToString();
}
Related
In my code I am trying to CREATE INDEX in my code, and since CREATING duplicated INDEX is not allowed, I wanted to check if my INDEX existed in my SQL CE Database.
In C# code, I ran the query using IDbCommand with query "SELECT * FROM INFORMATION_SCHEMA.INDEXES WHERE TABLE_NAME = 'mytablename'" so if there are results, I have the INDEX already created for this Database. Nothing fancy. However, when I run this, I did not see the result even though I know I created the index.
So I tried just running the query using SQL Server Compact/SQLite Toolbox. I am seeing that I have the INDEX with the tool's querying. I thought my SQL syntax might be wrong so I ran query "SELECT * FROM INFORMATION_SCHEMA.INDEXES" without WHERE to compare how many results I receive. I am seeing 13 results vs 12 results. Obviously the missing one is mytablename.
Does anybody have clue why this weird issue is occuring? If this is does not resolve, I can try catch and catch if there is duplicate and ignore the result. But preferably, I would like to properly catch if the Row exists or not.
The C# code I used is following.
DbProviderFactory factory = DbProviderFactories.GetFactory(provider);
using (DbConnection conn = factory.CreateConnection())
{
conn.ConnectionString = "xxxx";
try
{
conn.Open();
IDbCommand cmd = factory.CreateCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM INFORMATION_SCHEMA.INDEXES WHERE TABLE_NAME = 'mytablename'";
DbDataReader ddr = (DbDataReader)cmd.ExecuteReader();
ddr.Read();
}
catch (Exception ex)
{
}
finally
{
conn.Close();
}
}
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.
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.
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]