Why is the SELECT results different between SQL Query and DbDataReader Read() - c#

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();
}
}

Related

c# MySqlCommand.ExecuteNonQuery() return -1

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();
}

SELECT ##IDENTITY in Access always returning 0

I have been trying to find a solution to this problem but so far nothing worked.
private void Insert()
{
string ConnectionStringAccess = Provider=Microsoft.ACE.OLEDB.12.0;Data Source=###Jet OLEDB:Database Password=###;
string query2 = "Select ##Identity";
int id = -1;
string Query = "INSERT INTO tblTable (EmpNo, Name) VALUES (132, 'TestName');";
OleDbConnection con = new OleDbConnection(ConnectionStringAccess);
OleDbCommand cmd = new OleDbCommand(Query, con);
try
{
con.Open();
if (cmd.ExecuteNonQuery() == 1)//the insert succeded
{
cmd.CommandText = query2;
id = Convert.ToInt32(cmd.ExecuteScalar());
}
}
catch (Exception ex)
{
//log the ex
}
finally
{
con.Dispose();
con.Close();
}
}
Each time I use the above method I always get a return of 0 in "id". What am I doing wrong? I tried using a different connection string or another way to get latest identifier:
Provider=Microsoft.Jet.OLEDB.4.0;
SCOPE_IDENTITY()
but again nothing. The Access db is 2003 or older (not sure exactly).
The ms access db is 2003 or older (not sure exactly)
I was able to recreate your issue with an Access 97 database. SELECT ##IDENTITY worked correctly with an Access 2000 database file (even when run from the same OleDbCommand object as the INSERT), but it always returned zero when run against an Access 97 database.
It appears that you will need to upgrade your database file to a newer version if you want SELECT ##IDENTITY to work.
You are using the same command object for both the insert and retrieval of ##identity.
According to this article you should create a separate command object for retrieving the ##identity value:
http://support.microsoft.com/kb/815629
Also, just to verify, the table you are inserting to does have an auto increment column, is that correct? If not, ##identity would not return anything.
Create two different commands for your queries, execute non query then execute scalar. It will return the first column of the first row in the result set returned by the query and it should be the id you're looking for.
private void Insert()
{
string ConnectionStringAccess = Provider=Microsoft.ACE.OLEDB.12.0;Data Source=###Jet OLEDB:Database Password=###;
int id = -1;
string Query = "INSERT INTO tblTable (EmpNo, Name) VALUES (132, 'TestName')";
string Query2 = "SELECT ##Identity";
OleDbConnection con = new OleDbConnection(ConnectionStringAccess);
OleDbCommand cmd = new OleDbCommand(Query, con);
OleDbCommand cmd2 = new OleDbCommand(Query2, con);
try
{
con.Open();
cmd.ExecuteNonQuery();
id = (int)cmd2.ExecuteScalar();
}
catch (Exception ex)
{
//log the ex
}
finally
{
con.Dispose();
con.Close();
}
}
thanks for all the responses. I found out what the problem was. Apparently the access file is very old, 1997 to be exact and that was the problem. As soon as a tried a new access 2010 file it worked.
Thanks again
My soluce with my very older databases (VB6 and ACCESS)
With VB NET and before upgrade Database to 4.
'MyInsertCommand.CommandText = "Select ##Identity" Don't work with old Access database
MyInsertCommand.CommandText = "SELECT TOP 1 ME_idn FROM MESURE ORDER BY ME_idn Desc"
Dim MyInsertIdn As Integer = MyInsertCommand.ExecuteScalar()

Issue with conducting SQL statement within ASP.Net C# code

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]

Getting MySQL record count with C#

I would like to know how can I get record count of a query with C#.
Here is the code that I use..
MySqlDataReader recordset = null;
query = new MySqlCommand("SELECT * FROM test ORDER BY type_ID ASC", this.conn);
recordset = query.ExecuteReader();
while (recordset.Read())
{
result.Add(recordset["type_ID"].ToString());
}
return result;
I was using a SELECT COUNT(*) and expected an int to be returned. You may need this to get a usable value:
mysqlint = int.Parse(query.ExecuteScalar().ToString());
A couple of things...
The SQL statement you would use is:
SELECT COUNT(*) FROM test
However, when using the MySQL Connector/Net to connect to MySQL through C# there is some care to be given when handling query results.
For example, as cited in this question and on Microsoft Connect int.Parse("0") equivalently known as Int32.Parse("0") can throw a FormatException on some machines.
I have found that Convert.ToInt32 handles this case nicely.
So your code will be something like this:
using (var conn = new MySqlConnection(cs))
{
conn.Open();
using (var cmd = new MySqlCommand("SELECT COUNT(*) FROM test", conn))
{
int count = Convert.ToInt32(cmd.ExecuteScalar());
return count;
}
}
Remember to make use of using statements in order to ensure that the MySQL objects get disposed of properly.
You're adding a new element in result for each row. Depending on the type of result you should be able to do something like result.Count after the while loop completes.
You could run another query first to get the count :
query = new MySqlCommand("SELECT count(*) as theCount FROM test ORDER BY type_ID ASC", this.conn);
but in truth, you are probably best changing the problem so you wont need the count until after you have populated the list.

C# .net Concurrency Problems - SQL Connection then ADO.net changes

I have a c# .net program where I need to first insert data into a table using a sql connection and then adjust the same set of data using ADO.net. I am not sure how to make sure the insert via the sql connection is complete before doing the ado.net changes. I am getting a concurrency violation when I try the code below. I would guess that this is a race condition problem.
I am getting a concurrency violation error at the point of the UpdateAll statement and I can't seem to work around it
Thanks for the help.
Below is an example of the code with the SQL and ado.net changes dramatically simplified.
try
{
String deleteQuery = "DELETE FROM dbo.TABLENAME";
String reportQuery = #"
INSERT INTO TABLENAME
(
COLUMN1,
COLUMN2,
COLUMN3
)
SELECT
COLUMN1,
COLUMN2,
COLUMN3
FROM OTHERTABLES
";
SqlConnection ReportConnect = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.Connection = ReportConnect;
cmd.CommandTimeout = Convert.ToInt32(Properties.Settings.Default.ReportTimeout.ToString());
ReportConnect.Open();
cmd.CommandText = deleteQuery;
cmd.ExecuteNonQuery();
cmd.CommandText = reportQuery;
cmd.ExecuteNonQuery();
ReportConnect.Close();
ReportConnect.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
try
{
foreach (DataRow dr in DataSet.TABLENAME)
{
dr[0] = whatever;
dr[0] = 100;
dr[0] = 42.42;
}
}
catch (Exception ax)
{
MessageBox.Show(ax.Message);
}
finally
{
this.tableAdapterManager.UpdateAll(this.DataSet);
}
The problem here is that the "tableAdapterManager" appears to be created and opened before the data changes are made (with the sqlcommand). If you create the SqlDataAdapter with the wizard, by default the concurrency mode is optimistic (so the update and delete statement detect if the database has changed...) and fails with the exception you expose.
You can solve this issue in the wizard windows "Generate the SQL statements", click on the "Advanced Options" and uncheck the "Use optimistic concurrency" option.
Also you can change this from the form.designes.cs file, look for the UpdateCommand of the SqlDataAdapter and make sure that in the creation of the SqlParameter the DataRowVersion is set to "Default" or use another constructor.
In theory ExecuteNonQuery would not complete until the SQL had run, rendering your question moot. If you were deliberately executing asynchronously it would be a different matter, but you're not.
You should still be aware of issues caused by multiple concurrent users, of course.

Categories

Resources