the below coding getting execute but the value was not printing in screen
protected void Button1_Click(object sender, EventArgs e)
{
if (CheckBox1.Checked)
{
string OIMSquery = "SELECT COUNT(name) AS PolicySold FROM TestDate WHERE name='divi'";
SqlCommand OIMScmd = new SqlCommand(OIMSquery, OIMS_01);
OIMS_01.Open();
OIMScmd.ExecuteNonQuery();
OIMS_01.Close();
}
}
You should call ExectueScaler like
int count = (int) OIMScmd.ExecuteScalar();
ExecuteScalar
Executes the query, and returns the first column of the first row in
the result set returned by the query. Additional columns or rows are
ignored.
use ExecuteScalar() to fetch single value
string OIMSquery = "SELECT COUNT(name) AS PolicySold FROM TestDate WHERE name='divi'";
SqlCommand OIMScmd = new SqlCommand(OIMSquery, OIMS_01);
OIMS_01.Open();
int _result = Convert.ToInt32(OIMScmd.ExecuteScalar());
OIMS_01.Close();
ExecuteScalar()
You've got a query. Therefore this call is inappropriate:
OIMScmd.ExecuteNonQuery();
Instead, you should be using ExecuteScalar():
int count = (int) OIMScmd.ExecuteScalar();
(It's possible that it'll return a long rather than an int - I'm not sure offhand.)
Additionally, you should use a using statement for the SqlCommand and create a new connection for each operation:
using (var connection = new SqlConnection(...))
{
connection.Open();
using (var command = new SqlCommand(query, connection))
{
int count = (int) command.ExecuteScalar();
// Now use the count
}
}
It's also not clear what kind of app this is - if it's in a local GUI (WinForms or WPF) you should not be performing database access on the UI thread. The UI will be frozen while the database access occurs. (If this is in a web application, it's even more important that you create a new database connection each time... you don't want two separate requests trying to use the same connection at the same time.)
Use SqlCommand.ExecuteScalar() instead of ExecuteNonQuery() which returns nothing.
You need to use: ExecuteScalar()
Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored.
int result = Convert.ToInt32(OIMScmd.ExecuteScalar());
Instead of
OIMScmd.ExecuteNonQuery();
You can use SqlCommand.ExecuteScalar method;
Executes the query, and returns the first column of the first row in
the result set returned by the query. Additional columns or rows are
ignored.
int i = (int)OIMScmd.ExecuteScalar();
Since this method returns object, you should implicity convert it to int.
using (SqlConnection OIMS_01 = new SqlConnection(connString))
{
SqlCommand OIMScmd = new SqlCommand(OIMSquery, OIMS_01);
try
{
OIMS_01.Open();
int i = (int)OIMScmd.ExecuteScalar();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Try, OIMScmd.ExecuteReader(); method which returns the object of SqlDataReader class then read the value from it.
OR
use, Convert.ToInt32(OIMScmd.ExecuteScalar()) and then print the value.
Related
I'm loading data into a form with 3 Entry controls.
The object I am using for this is called mySettings, which is an object of SystemSettings, a class and database table in my SQLite database.
So far I have this code, and it works as is.
var db = new SQLiteConnection(dbPath);
Entry txtServer;
txtServer = new Entry { FontSize = 10 };
controlGrid.Children.Add(txtServer, 2, 0);
Grid.SetColumnSpan(txtServer, 4);
SystemSettings mySettings;
mySettings = db.Get<SystemSettings>(0);
txtServer.Text = mySettings.FTPServer;
However, I need to check whether SystemSettings contains any rows in the table before I load values in.
I've seen a few guides online.
Some say use something along the lines of
SQLiteCommand cmd;
cmd = new SQLiteCommand(db);
...
int result = Convert.ToInt32(db.ExecuteScalar)
However, I get an error there saying
SQLiteCommand does not contain any method containing x parameters
no matter how many I pass in (0 or more).
There also doesn't appear to be a method as part of db.
So how can I check whether SystemSettings contains any rows, before trying to use data that doesn't exist?
The pattern below should work. The .ExecuteScalar() method is actually on the command and not the connection.
int count;
using (SQLiteConnection db = new SQLiteConnection("MY_CXN_STRING"))
using (SQLiteCommand cmd = new SQLiteCommand("SELECT COUNT(*) FROM SystemSettings"))
{
db.Open();
count = (int)cmd.ExecuteScalar();
db.Close();
}
bool hasRows = count != 0;
Basically you want to clear
SystemSettings
Try just running a query that returns nothing against the database. For instance:
SystemSettings = $"SELECT * FROM TABLE_NAME WHERE COLUMN_NAME IS 'INVALID_EXPRESSIONdjeiq48724rufnjdrandom stuff'";
Not the most elegant solution by any means, but it works.
What you want to do is to get the first row in you SystemSettings table if any:
You should therefore execute the following Sql Statement (or something similar) and check if a result is returned:
Select * from SystemSettings LIMIT 1;
You can execute the query and check the result like this:
public bool DoesTableContainRows(string tableName, SQLiteConnection connection)
{
var command = new SQLiteCommand($"Select * from {tableName } LIMIT 1;", connection);
var resultReader = command.ExecuteReader();
// check whether or not a row was returned
bool containRows = resultReader.Read();
resultReader.Close();
return containRows;
}
Edit:
Shows how to check if a table contains rows using .NET and Microsoft.Data.Sqlite including better disposing of resources.
public bool DoesTableContainRows(string tableName, SqliteConnection connection)
{
using (var command = new SqliteCommand($"Select * from {tableName } LIMIT 1;", connection))
{
using (var resultReader = command.ExecuteReader())
{
// check whether or not a row was returned
bool containRows = resultReader.Read();
resultReader.Close();
return containRows;
}
}
}
I have the following method that sets an object to a specific status (it sets a column value of a specific row to '4' :
C#
void setObjectToFour(int objectID)
{
using (var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["Database"].ConnectionString))
using (var command = new SqlCommand("setObjectToFour", conn)
{
CommandType = CommandType.StoredProcedure
})
{
command.Parameters.Add(new SqlParameter("#objectID", SqlDbType.Int)).Value = objectID;
conn.Open();
command.ExecuteNonQuery();
}
}
SQL:
...
AS
BEGIN
Update [DB_OBJECT].[dbo].[object_table]
SET status = 4
WHERE id = #objectID
END
The problem is that the DB_OBJECT DB is not managed by us and is the DB of a piece of software.
The followed problem is that the query from above not always works (and we haven't figured out why) and I were thinking about how we could 'force' or 'check' if the row was updated.
Is it smart to do it as follow?:
1 - Create new C# Method Check and stored procedure getStatus that retrieves the status of the object
2 - I will put both methods from above in a do while until the status is 4.
Is this a smart approach?
ExecuteNonQuery() method returns the number of rows affected.
int recordAffectd = command.ExecuteNonQuery();
if (recordAffectd > 0)
{
// do something here
}
ExecuteNonQuery() does not return data at all: only the number of rows affected by an insert, update, or delete.
try this
if (command.ExecuteNonQuery() != 0)
{
// more code
}
i insert the data from datagridview to database table. but the error that come in the exception i write in the title. the value save in the database table as well.
private void btnSavePurchases_Click(object sender, EventArgs e)
{
if ((string.IsNullOrEmpty(txtPGrandTotal.Text)) || (txtPGrandTotal.Text == "0"))
{
MessageBox.Show("No record available");
}
else
{
try
{
string query1 = "INSERT INTO purchases (productId) values (#product_Id)";
command = DBConnectivity.getCommandForQuery(query1, connection);
for (int i = 0; i < dGvPurchases.Rows.Count; i++)
{
// command.Parameters.Clear();
command.Parameters.AddWithValue("product_Id", dGvPurchases.Rows[i].Cells[9].Value);
command.ExecuteNonQuery();
}
}
catch (Exception ex)
{
}
}
}
Probably
AddWithValue("product_Id"...
should be
AddWithValue("#product_Id"...
By the way, since you add your parameters in a for loop, you need clear them top of your for loop. That's why you need to uncomment your command.Parameters.Clear() part. Without Clear method, you try to add same parameter name over and over again to same command and you will get an error in your second iteration.
As an another solution, you can declare your parameter name outside of your loop and add it's value inside of loop.
And don't use AddWithValue as much as possible. It may generate unexpected results sometimes. Use .Add() overloads to specify your db type and it's size.
Don't forget to use using statement as well to dispose your command object.
I don't see command anywhere in the scope here. Probably it is a class variable. That is one part of your issue.
Move the construction of the command variable to inside your method:
var command = DBConnectivity.getCommandForQuery(...);
^^^
Second, your for look causes issues. You can't add the same parameter over and over again. If you want to insert multiple rows, add multiple insert statements. Create the command inside the for loop.
problem is that command.Parameters.AddWithValue adds the parameter to the list of parameters. you can't add a parameter twice. since you call the command several times, define the parameter outside and set value within the loop:
string query1 = "INSERT INTO purchases (productId) values (#product_Id)";
command = DBConnectivity.getCommandForQuery(query1, connection);
// Define the Parameter just once
var param = command.Parameters.Add("#product_Id", SqlDbType.Int);
for (int i = 0; i < dGvPurchases.Rows.Count; i++)
{ // set value while looping
param.Value = dGvPurchases.Rows[i].Cells[9].Value;
command.ExecuteNonQuery();
}
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 have a winforms app that includes the following class method:
public aSqlQuery(SqlCommand pSqlCom, string pMode = "object", bool pGetID = false)
{
try
{
string strConnection = aSystem.ConnectionString;
SqlConnection linkToDB = new SqlConnection(strConnection);
pSqlCom.Connection = linkToDB;
switch (pMode)
{
case "non query":
{
linkToDB.Open();
pSqlCom.ExecuteNonQuery();
if (pGetID == true)
{
SqlCommand sqlCom = new SqlCommand("SELECT ##IDENTITY;", linkToDB);
this.LastID = (int)sqlCom.ExecuteScalar();
}
linkToDB.Close();
}
break;
plus other switches
The pSqlCom (SqlCommand) executes fine becuase I can see the data written into the database. However the subsequent "SELECT ##IDENTITY" statement gives an invalid cast error
What am I doing wrong and how can I retrieve the new ID created by SQL within my class method?
Insert the row and get the Id it is was given with SCOPE_IDENTIY(), don't use ##IDENTITY.
You need to use SCOPE_IDENTITY() on the same connection and scope, just after the INSERT.
In your example no INSERT is performed on your connection so you can't expect to get the last generated Id.
In your example its not clear that pSqlCom performs an INSERT, if it does not any indentity function will return NULL which cannot be converted to int
EDIT
You want to use SCOPE_IDENTITY() and you want to do it in the same Command as the INSERT.
So, your statement should be somthing like
var sql =
#"INSERT <Your Data> <Your Table>;
SELECT SCOPE_IDENTIY();"
using (SqlConnection connection = new SqlConnection(strConnection))
{
using (SqlCommand command = new SqlCommand(sql, connection))
{
connection.Open();
object result = command.ExecuteScalar();
}
}
int? id = (int?)(!Convert.IsDBNull(result) ? result : null);
The correct answer it turns out was that the SELECT SCOPE_IDENTITY() statement had to form part of the same SqlCommand as the INSERT statement which preceeded it, but which I had contained in the previous SqlCommand 'pSqlCom'. Once the SELECT SCOPE_IDENTITY() was incuded as part of pSqlCom the code correctly returned the Identity.
Your call to the command should be returning something not of scalar type. Indeed you need to use Int32 instead. Chek ExecuteScalar on MSDN.
Also, I recommend you to use SCOPE_IDENTITY() instead of ##Identity. Check the following link for a detailed explanation.