MySql get number of rows - c#

I try to get number of rows from a table with this :
string commandLine = "SELECT COUNT(*) FROM client";
using (MySqlConnection connect = new MySqlConnection(connectionStringMySql))
using (MySqlCommand cmd = new MySqlCommand(commandLine, connect))
{
connect.Open();
int count = (int)cmd.ExecuteScalar();
return count;
}
And i get the exception:
Specified cast is not valid.
Any idea how i can fix it?

Try this
using (MySqlCommand cmd = new MySqlCommand(commandLine, connect))
{
connect.Open();
return Convert.ToInt32(cmd.ExecuteScalar());
}

using (MySqlCommand cmd = new MySqlCommand(commandLine, connect))
{
connect.Open();
return Convert.ToInt32(cmd.ExecuteScalar());
}
EDIT: Make also sure to handle exceptions in your code (E.g. if there is SQL Connection Error).
Also, if it's not a COUNT(*) the value returned by ExecuteScalar() can be null (!)

If you wish to use the cast, you can use:
long count = (long)cmd.ExecuteScalar();
As mentioned above, COUNT in MySql returns BIGINT, hence casting with an int fails.

Related

C# SQL Add parameter

I tried to return a row by executing following SQL query in C#:
SqlCommand cmd = new SqlCommand();
string selectquery = "SELECT TOP (1) [ZVNr] ZVNR_TABLE WHERE [ZVNr] = #zvnr order by [ZVNr] DESC";
cmd.Parameters.AddWithValue("#zvnr", "20170530-01");
cmd.CommandText = selectquery;
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection;
try
{
sqlConnection.Open();
int recordsAffected = cmd.ExecuteNonQuery();
if(recordsAffected != -1)
{
return 0;
}
else
{
return 1;
}
And the "ZVNR_TABLE" looks like this:
ZVNR | varchar (50)
20170530-01
The result is always --> recordsAffected = -1
Although when I'm executing the same SQL query in Microsoft SQL Server Management Studio, it works.
You're using a SELECT statement in your code with cmd.ExecuteNonQuery which is used for INSERT or UPDATE statements.
You have to use a SQLDataReader (more than 1 row and(!) column) or Scalar (1 row/1col = one "item").
MSDN Example for SQLDataReader:
//SELECT col1, col2, ..., coln FROM tbl;
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
Console.WriteLine("{0}\t{1}", reader.GetInt32(0),
reader.GetString(1));
}
}
else
{
Console.WriteLine("No rows found.");
}
reader.Close();
MSDN Example for ExecuteScalar:
//SELECT COUNT(*) FROM region; or any other single value SELECT statement
int count = (int)cmd.ExecuteScalar(); //cast the type as needed
If you want the affected count after you change items in your database, you can get it by using cmd.ExecuteNonQuery which returns that count:
MSDN Example for ExecuteNonQuery:
//INSERT INTO tbl (...) VALUES (...) or any other non-query statement
int rowsAffected = (Int32)cmd.ExecuteNonQuery();
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command.
Because you are Selecting the data from the datatable not inserting or updating the records that's why recordsAffected is always -1
Answers given above are ok but if you want just to see if it exist you can do a count instead
using (SqlConnection connection = new SqlConnection(connectionstring))
{
string query = "SELECT Count([ZVNr]) ZVNR_TABLE WHERE [ZVNr] = #zvnr order by [ZVNr] DESC";
using (SqlCommand cmd = new SqlCommand(query, connection))
{
cmd.Parameters.AddWithValue("#zvnr", "20170530-01");
try
{
connection.Open();
int result = (int)cmd.ExecuteScalar();
}
}
}
ExecuteNonQuery() is used for INSERT or UPDATE statements and returns the number of rows affected.
If you want to return a single field of a row, you have to use ExecuteScalar()
using (SqlConnection connection = new SqlConnection(connectionstring))
{
string query = "SELECT TOP (1) [ZVNr] ZVNR_TABLE WHERE [ZVNr] = #zvnr order by [ZVNr] DESC";
using (SqlCommand cmd = new SqlCommand(query, connection))
{
cmd.Parameters.AddWithValue("#zvnr", "20170530-01");
connection.Open();
object result = cmd.ExecuteScalar();
}
}

C# MySql Parameterized Query makes longs into null

The code is based on https://dev.mysql.com/doc/connector-net/en/connector-net-programming-prepared-preparing.html
public void TableTest(string connectionString)
{
string sqlToCreateTable = #"CREATE TABLE IF NOT EXISTS my_table
(auction_key BIGINT NOT NULL, auction_owner VARCHAR(25), first_seen BIGINT,
PRIMARY KEY(auction_key))";
string sqlInsertOrUpdateAuction = "INSERT INTO my_table (auction_key) VALUES (#my_auc_id); ";
using (MySqlConnection dbConnection = new MySqlConnection(connectionString))
{
dbConnection.Open();
// is the table in the database?
MySqlCommand cmd = new MySqlCommand(sqlToCreateTable, dbConnection);
cmd.ExecuteNonQuery();
cmd.Parameters.AddWithValue("#my_auc_id", 123456);
cmd = new MySqlCommand(sqlInsertOrUpdateAuction, dbConnection);
cmd.ExecuteNonQuery();
}
}
The error is that 123456 is seen as null.
Message=Column 'auction_key' cannot be null
I tried changing the "strict" setting in my.ini and it makes no difference.
Help please.
Well, you add the parameter to the command and then instantiate a new command:
cmd.Parameters.AddWithValue("#my_auc_id", 123456);
cmd = new MySqlCommand(sqlInsertOrUpdateAuction, dbConnection);
If you do that, the command will no longer have the value for the #my_auc_id. Try switching those two lines:
cmd = new MySqlCommand(sqlInsertOrUpdateAuction, dbConnection);
cmd.Parameters.AddWithValue("#my_auc_id", 123456);
Hope this helps.
You could alleviate your issue, by simply doing the following:
using(var connection = new MySqlConnection(dbConnection))
{
connection.Open();
using(var command = new MySqlCommand(createTableQuery, connection))
{
command.ExecuteNonQuery();
}
using(var command = new MySqlCommand(insertOrUpdate, connection))
{
command.Parameters.Add("..", SqlDbType = SqlDbType.Int).Value = 123456;
command.ExecuteNonQuery();
}
}
Keep in mind that ExecuteNonQuery will return a zero or one, if it successfully worked. Also you may want to manually specify the SqlDbType. To avoid SQL inferring incorrectly. Also, this will correctly scope your MySqlCommand, so you can correctly utilize for the queries.
And according to the documentation, it does implement the IDisposable to utilize the using block. This ensures you instantiate your MySqlCommand again.

Why am I getting "Invalid Cast Exception" with this SQLite code?

I've got this code to get a count from a SQLite table:
internal static bool TableExistsAndIsNotEmpty(string tableName)
{
int count;
string qry = String.Format("SELECT COUNT(*) FROM {0}", tableName);
using (SQLiteConnection con = new SQLiteConnection(HHSUtils.GetDBConnection()))
{
con.Open();
SQLiteCommand cmd = new SQLiteCommand(qry, con);
count = (int)cmd.ExecuteScalar();
}
return count > 0;
}
When it runs, I get, "Invalid Cast Exception"
As is probably obvious, the value being returned from the query is an int, that is to say the count of records (I get "2" when I run the query, namely "SELECT COUNT(*) FROM WorkTables" in Sqlite Browser).
So what is being invalidly cast here?
As a sort of a side note, I know it's better to use query parameters, and I found out how to do this in a Windows Store App here [How can I use SQLite query parameters in a WinRT app?, but don't know how to do it in an oldfangled (Windows Forms/Windows CE) app.
I would think it would be something like this:
string qry = "SELECT COUNT(*) FROM ?";
using (SQLiteConnection con = new SQLiteConnection(HHSUtils.GetDBConnection()))
{
con.Open();
SQLiteCommand cmd = new SQLiteCommand(con);
count = cmd.ExecuteScalar(qry, tableName);
}
...but nothing of the ilk that I tried compiled.
In this context the ExecuteScalar returns a System.Int64.
Applying the (int) cast creates the exception you are seeing
object result = cmd.ExecuteScalar();
Console.WriteLine(result.GetType()); // System.Int64
You could solve your problem with Convert.ToInt32
SQLiteCommand cmd = new SQLiteCommand(qry, con);
count = Convert.ToInt32(cmd.ExecuteScalar());

Insert/Update in asp.net and SQL SERVER 2008

I am trying to insert a record if requested prodName doesnot exist in database. If it exists I want to update the value of quantity attribute. I have used the following it neither inserts nor Updates any record. I get following exception:
ExecuteScalar requires an open and available Connection. The connection's current state is closed
This is the code
public static void manageStock(CompanyStock stock)
{
///// Check if record exists/////////
cmd = new SqlCommand("select count(*) from tblStock where prodName=#prodName", con);
cmd.Parameters.AddWithValue("#prodName", stock.prodName);
con.Open();
Int32 count = (Int32)cmd.ExecuteScalar(); //returns null if doesnt exist
con.Close();
if (count > 0)
{
cmd = new SqlCommand("update tblStock set quantity = #quantity where prodName=#prodName", con);
cmd.Parameters.AddWithValue("#prodName", stock.prodName);
cmd.Parameters.AddWithValue("#quantity", stock.quantity);
}
else
{
cmd = new SqlCommand("insert into tblStock(prodName,quantity) values (#prodName, #quantity)", con);
cmd.Parameters.AddWithValue("#prodName",stock.prodName);
cmd.Parameters.AddWithValue("#quantity",stock.quantity);
}
try
{
con.Open();
cmd.ExecuteNonQuery();
}
finally
{
con.Close();
}
}
}
Edited
I edited my code. It works fine now. I had to open my connection before executing ExecuteScalar But I want to know the standard way of writing this opening and closing stuff. It looks kind of haphazard. How can I improve this?
You can use Convert.ToInt32() method for converting the result into integer value.
if the value is null it converts it into 0.
Try This:
int count = Convert.ToInt32(cmd.ExecuteScalar());
Consider using MERGE clause in sql-server. Here is a good Microsoft article you can use.
What does it do when you step through the code?
In some SQL collations (Latin1_General_BIN for example), variables are case sensitive. In your first select statement you have #ProdName in your query and #prodName in your parameters collection. If you have a case sensitive collation, you're never getting past this part. Right-click on the database in Management Studio and click Properties to find the collation.
Error say that there's no connection.May u check first of all that issue so
Check connection and if is not null and exist at this point check it con.State = Open or any other value. I connection state is closed open it.But first of all where is connections declaration ? i don't see it in your code.
TRY THIS :
//USING THE STATEMNET USING IT WILL TAKE CARE TO DISPOSE CONNECTION AND PLACE TRY CATCH WITHIN PROCS
{
using (SqlConnection cnn = new SqlConnection(ConfigurationManager.AppSettings("connectionString"))) {
if (cnn.State == System.Data.ConnectionState.Closed)
cnn.Open();
using (SqlCommand cmd = new SqlCommand()) {
try {
cmd.Connection = cnn;
cmd.CommandText = "YOUR SQL STATEMENT";
int I = Convert.ToInt32(cmd.ExecuteNonQuery);
if (I > 0)
{
cmd.CommandText = "YOUR SQL STATEMENT";
//ADDITIONAL PARAMTERES
}
else
{
cmd.CommandText = "YOUR SQL STATEMENT";
//ADDITIONAL PARAMETERS
}
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
}
}
You can try this code. First write a stored procedure:
CREATE PROCEDURE sprocquanupdateinsert
#prodName nvarchar(250),
#quantity int
AS
BEGIN
UPDATE tblStock
SET quantity = #quantity
WHERE prodName = #prodName
IF ##ROWCOUNT = 0
INSERT INTO tblStock(prodName, quantity)
VALUES (#prodName, #quantity)
END
GO
Then in code behind you can use this
using (conn)
{
SqlCommand cmd = new SqlCommand("sprocquanupdateinsert", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#prodName", stock.prodName);
cmd.Parameters.AddWithValue("#quantity", stock.quantity);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}

SQL SELECT With Stored Procedure and Parameters?

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

Categories