I have a MySql table from which I fetch data to my C# application. Randomly some data are inserted in this table form another source. I want to fetch those data continuously in my C# application. My DB connection and select query are following :
string connection = "Server=localhost;Database=intel;Uid=root;Pwd=";
MySqlConnection dbcon = new MySqlConnection(connection);
MySqlCommand selectData;
dbcon.Open();
selectData = dbcon.CreateCommand();
selectData.CommandText = "SELECT user_id, user_name,user_type FROM win_user ORDER BY user_id ASC ";
MySqlDataReader rdr = selectData.ExecuteReader();
I want to execute my select query unit it get any data.
if
Get data = null
execute my select query again
else
Get data = data
execute my next code
I think it can be happen with while loop, but I dont know how ? Can any onk help me ?
What you want to do sounds odd but, to answer the question as asked, you can use a loop like so:
MySqlDataReader rdr = selectData.ExecuteReader();
// Check whether the result set is empty.
while (!rdr.HasRows)
{
rdr.Close();
// Pause before trying again if appropriate.
rdr = selectData.ExecuteReader();
}
while (rdr.Read())
{
// Read data here.
}
use this
If(rdr.HasRows)
{
rdr.Read();
// do your logic
}
rdr.Close();
use rdr.Read() only when you have some data in datareader object.
if you simply want to read values without checking null than use this
while (rdr.Read())
{
// do logic
}
rdr.Close();
this loop runs as many times as no of rows exist in your select query result.
Related
Would you please show me how to retrieve data from SQL Server to C# (Windows Forms application)?
Consider I have a textbox and I need to fill it with data from SQL Server WHERE 'emp_id = something' for example, how can I do it without a DataGridView?
Or take this another example:
SELECT sum(column) FROM table_name
How to get the value of the above command (also without a DataGridView)?
There are multiple ways to achieve this. You can use DataReader or DataSet \ DataTable. These are connected and disconnected architectures respectively. You can also use ExecuteScalar if you want to retrieve just one value.
Recommendations:
Enclose SqlConnection (and any other IDisposable object) in using block. My code uses try-catch block.
Always use parameterized queries.
Following is some example code with DataReader in case your query returns multiple rows. The code is copied from here.
//Declare the SqlDataReader
SqlDataReader rdr = null;
//Create connection
SqlConnection conn = new SqlConnection("Your connection string");
//Create command
SqlCommand cmd = new SqlCommand("Your sql statement", conn);
try
{
//Open the connection
conn.Open();
// 1. get an instance of the SqlDataReader
rdr = cmd.ExecuteReader();
while(rdr.Read())
{
// get the results of each column
string field1 = (string)rdr["YourField1"];
string field2 = (string)rdr["YourField2"];
}
}
finally
{
// 3. close the reader
if(rdr != null)
{
rdr.Close();
}
// close the connection
if(conn != null)
{
conn.Close();
}
}
In case your query returns single value, you can continue with above code except SqlDataReader. Use int count = cmd.ExecuteScalar();. Please note that ExecuteScalar may return null; so you should take additional precautions.
Filling a Textbox:
using (var sqlConnection = new SqlConnection("your_connectionstring"))
{
sqlConnection.Open();
using (var sqlCommand = sqlConnection.CreateCommand())
{
sqlCommand.CommandText = "select sum(field) from your_table";
object result = sqlCommand.ExecuteScalar();
textBox1.Text = result == null ? "0" : result.ToString();
}
sqlConnection.Close();
}
for reading more than one row you can take a look at SqlCommand.ExecuteReader()
You need to use direct database access such as in the System.Data.SqlClient Namespace which is documented here System.Data.SqlClient Namespace.
Basically, look up creating a SQLConnection and SQLCommand and using them to retrieve the data.
I am new to Visual C# programming language and recently i was trying to make a application that is supposed to insert into a local database of users some data but every times my code runs and the insertion works fine the database does not update.This is the code that i am using
try
{
cn.Open();
SqlCommand insert = new SqlCommand();
insert.CommandText = "insert into Clienti (Nume,Prenume,Parola,Email) values(#Nume,#Prenume,#Parola,#Email)";
insert.Connection = cn;
insert.Parameters.AddWithValue("#Nume", register_nume.Text);
insert.Parameters.AddWithValue("#Prenume", register_prenume.Text);
insert.Parameters.AddWithValue("#Parola", register_password.Text);
insert.Parameters.AddWithValue("#Email", register_email.Text);
insert.ExecuteNonQuery();
SqlDataReader reader = insert.ExecuteReader();
while (reader.Read()) { }
MessageBox.Show("Added succesfully");
}
catch (Exception ex)
{
MessageBox.Show(""+ex);
}
I already tried the property Copy to output and it doesn't seems to work.
I am sorry for any grammar mistakes that i made,I would be grateful for any help.
insert.ExecuteNonQuery();
SqlDataReader reader = insert.ExecuteReader();
while (reader.Read()) { }
You only need the ExecuteNonQuery, it will run the INSERT. You need to use ExecuteReader instead only when you're running a statement that produces result sets (eg. SELECT). So it should be:
insert.ExecuteNonQuery();
Its because you have to now read the database using a select statement, you cant use an INSERT SQL statement to read.
You could add the following immediately after your insert.
using(var selectCmd = new SqlCommand("SELECT Nume,Prenume,Parola,Email FROM Clienti WHERE Nume = #Nume", cn))
{
selectCmd.Parameters.AddWithValue("#Nume", register_nume.Text);
using(SqlDataReader reader = selectCmd.ExecuteReader())
{
while (reader.Read()) { }
}
}
That said if you want to know IF the row was inserted or how many records were inserted ExecuteNonQuery returns the number of rows affected. You could change that part of the code like this:
var recordsAffected = insert.ExecuteNonQuery();
if(recordsAffected > 0)
MessageBox.Show("Added succesfully");
else
MessageBox.Show("Nothing happened");
Although in this particular case it would not make sense because if nothing was inserted it would probably be caused by an Exception.
Some side notes
Always wrap types that implement IDisposable in using blocks (see code above as example). It ensures that resources are always released as soon as you are done with them even if an Exception is thrown.
Never swallow Exceptions! Either recover from one and log it or do not catch it at all. If you swallow it you will never know if/why your code broke.
This part of your code is preparing the SQL command that you are running
cn.Open();
SqlCommand insert = new SqlCommand();
insert.CommandText = "insert into Clienti (Nume,Prenume,Parola,Email) values(#Nume,#Prenume,#Parola,#Email)";
insert.Connection = cn;
insert.Parameters.AddWithValue("#Nume", register_nume.Text);
insert.Parameters.AddWithValue("#Prenume", register_prenume.Text);
insert.Parameters.AddWithValue("#Parola", register_password.Text);
insert.Parameters.AddWithValue("#Email", register_email.Text);
The SQL command that your code is running, is an INSERT statement, which only adds a new record to your table.
This statement runs the command that you setup earlier:
insert.ExecuteNonQuery();
If I understand correctly, here you are trying to read the data from the table again:
SqlDataReader reader = insert.ExecuteReader();
while (reader.Read()) { }
Problem is, your command is NOT set for reading. To read data, you need to use a SELECT statement. Something like this:
insert.CommandText = "SELECT Nume,Prenume,Parola,Email from Clienti" ;
So, to read the data after executing the insert, you should do this:
insert.CommandText = "SELECT Nume,Prenume,Parola,Email from Clienti" ;
SqlDataReader reader = insert.ExecuteReader();
while (reader.Read()) { }
You ar executing 2 times the query:
insert.ExecuteNonQuery();
SqlDataReader reader = insert.ExecuteReader();
Try to get the affected rows
int rows = insert.ExecuteNonQuery();
I would suggest creating a stored procedure in your database and just execute the SP.
It's always better to execute SP from code and leave the SQL programming in the DB.
I am trying to check if there is a row present in a SQL Server table or not.
If the row exists (on a particular TicketID), it should show a messagebox that you can't continue further as there is already an entry in database. But if there isn't, it should insert some records (on that particular TicketID).
I tried try and catch but wasn't able to do it :
Here is the code of query: (hardcoded ticketID for example)
bool no;
try
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ST"].ConnectionString.ToString());
con.Open();
cmd.CommandText = "SELECT EngineerVisited from tblTicketTechnical where TicketID=1";
cmd.Connection = con;
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
bool = rdr.GetBoolean(0);
}
con.Close();
}
catch
{
MessageBox.Show("Cannot continue");
}
I would really appreciate if someone could suggest a function that will return true if row is found and return false, if it isn't.
You should follow the same logic in code as the logic you state in English: if there's already a ticket show a message and if not, insert some data.
var checkQuery = "SELECT COUNT(*) FROM tblTicketTechnical where TicketID=1";
var command = new OleDbCommand(checkQuery, con);
con.Open();
int count = (int)command.ExecuteScalar();
if(count > 0)
{
//Already exists, show message
}
else
{
var insertQuery = "INSERT INTO tblTicketTechnical(col1, col2) VALUES('val1', val2')";
con = new OleDbCommand(insertQuery, con);
con.ExecuteNonQuery();
}
Please mind that this is written out of my head and not tested. Nor have I implemented exception handling. This is just to show the logic how you can perform what you want to achieve.
You can use HasRows property of SQLDataReader.
A catch block will only be executed if your code throws an exception. Here it is simply not happening.
Instead of Try/Catch use if statements and checks on your query results.
Create procedure and code like this
IF NOT EXISTS (SELECT 1 FROM youtable WHERE id= #id)
BEGIN
RAISERROR ('Record Exists', 16, 2)
END
ELSE
Begin
INSERT INTO YOURTABEL(COLUM1,COLUM2) VALUES(VALUE1, VALUE2)
END
and then by try catch you can show message to user
You can use DataTableReader.HasRows Property
The HasRows property returns information about the current result set
Process
I am writing a C# application which will need to retrieve 4 million records(ID) from a SQL table in database A.
I then need to use each ID to select a row of record each from another SQL table in database B.
Once I have this row I then need to update another SQL table in database C
Questions
What’s the most efficient way to retrieve and store the data in Step 1?
a. Should I load this in a list string?
b. Do you recommend doing batches initially?
What the most efficient way to achieve steps 2 and 3
To retrieve the 4M records you're going to want to use a SqlDataReader - it only loads one row of data into memory at a time.
var cn = new SqlConnection("some connection string");
var cmd = new SqlCommand("SELECT ID FROM SomeTable", cn);
var reader = cmd.ExecuteReader();
while (reader.Read())
{
var id = reader.GetInt32(0);
// an so on
}
reader.Close();
reader.Dispose();
cn.Close();
Now, to handle two and three, I would leverage a DataTable for the row you need to retrieve and then a SqlCommand on the third database. This means that inside the reader.Read() you can get the one row you need by filling a DataTable with a SqlDataAdapter and the issuing an ExecNonQuery against a SqlCommand for the UPDATE statement.
Another way of writing the above, and it's a bit safer, is to use the using statement:
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var id = reader.GetInt32(0);
// an so on
}
}
that will eliminate the need for:
reader.Close();
reader.Dispose();
and so you could also issue that for the SqlConnection if you wanted.
SQLBulkCopy class might help.
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx
I can't seem to find why this function doesn't insert records into the database. :(
I get no error messages or whatsoever, just nothing in the database.
EDIT: this is how my query looks now .. still nothing ..
connection.Open();
XmlNodeList nodeItem = rssDoc.SelectNodes("/edno23/posts/post");
foreach (XmlNode xn in nodeItem)
{
cmd.Parameters.Clear();
msgText = xn["message"].InnerText;
C = xn["user_from"].InnerText;
avatar = xn["user_from_avatar"].InnerText;
string endhash = GetMd5Sum(msgText.ToString());
cmd.Parameters.Add("#endhash",endhash);
cmd.CommandText = "Select * FROM posts Where hash=#endhash";
SqlCeDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
string msgs = reader["hash"].ToString();
if (msgs != endhash || msgs == null)
{
sql = "INSERT INTO posts([user],msg,avatar,[date],hash) VALUES(#username,#messige,#userpic,#thedate,#hash)";
cmd.CommandText = sql;
cmd.Parameters.Add("#username", C);
cmd.Parameters.Add("#messige", msgText.ToString());
cmd.Parameters.Add("#userpic", avatar.ToString());
cmd.Parameters.Add("#thedate", dt);
cmd.Parameters.Add("#hash", endhash);
cmd.ExecuteNonQuery();// executes query
adapter.Update(data);// saves the changes
}
}
reader.Close();
}
connection.Close();
Does nodeItem actually have any items in it? If not, the contents of the foreach loop aren't being executed.
What's the adapter and data being used for? The queries and updates seem be done via other commands and readers.
What does 'hash' actually contain? If it's a hash, why are you hashing the content of the hash inside the while loop? If not, why is it being compared against a hash in the query SELECT * FROM posts WHERE hash = #endhash?
Won't closing the connection before the end of the while loop invalidate the reader used to control the loop?
Lots of things going on here...
You are using the command 'cmd' to loop over records with a datareader, and then using the same 'cmd' command inside the while statement to execute an insert statement. You declared another command 'cmdAdd' before but don't seem to use it anywhere; is that what you intended to use for the insert statement?
You also close your data connection inside the while loop that iterates over your datareader. You are only going to read one record and then close the connection to your database that way; if your conditional for inserting is not met, you're not going to write anything to the database.
EDIT:
You really should open and close the connection to the database outside the foreach on the xmlnodes. If you have 10 nodes to loop over, the db connection is going to be opened and closed 10 times (well, connection pooling will probably prevent that, but still...)
You are also loading the entire 'posts' table into a dataset for seemingly no reason. You're not changing any of the values in the dataset yet you are calling an update on it repeatedly (at "save teh shanges"). If the 'posts' table is even remotely large, this is going to suck a lot of memory for no reason (on a handheld device, no less).
Is anything returned from "Select * FROM posts Where hash=#endhash"?
If not, nothing inside the while loop matters....
Why are you closing the Database Connection inside the while loop?
The code you posted should throw an exception when you try to call cmd.ExecuteNonQuery() with an unopen DB connection object.
SqlCeCommand.ExecuteNonQuery() method returns the number of rows affected.
Why don't you check whether it is returning 1 or not in the debugger as shown below?
int rowsAffectedCount = cmd.ExecuteNonQuery();
Hope it helps :-)
You've got some issues with not implementing "using" blocks. I've added some to your inner code below. The blocks for the connection and select command are more wishful thinking on my part. I hope you're doing the same with the data adapter.
using (var connection = new SqlCeConnection(connectionString))
{
connection.Open();
var nodeItem = rssDoc.SelectNodes("/edno23/posts/post");
foreach (XmlNode xn in nodeItem)
{
using (
var selectCommand =
new SqlCeCommand(
"Select * FROM posts Where hash=#endhash",
connection))
{
var msgText = xn["message"].InnerText;
var c = xn["user_from"].InnerText;
var avatar = xn["user_from_avatar"].InnerText;
var endhash = GetMd5Sum(msgText);
selectCommand.Parameters.Add("#endhash", endhash);
selectCommand.CommandText =
"Select * FROM posts Where hash=#endhash";
using (var reader = selectCommand.ExecuteReader())
{
while (reader.Read())
{
var msgs = reader["hash"].ToString();
if (msgs == endhash && msgs != null)
{
continue;
}
const string COMMAND_TEXT =
"INSERT INTO posts([user],msg,avatar,[date],hash) VALUES(#username,#messige,#userpic,#thedate,#hash)";
using (
var insertCommand =
new SqlCeCommand(
COMMAND_TEXT, connection))
{
insertCommand.Parameters.Add("#username", c);
insertCommand.Parameters.Add(
"#messige", msgText);
insertCommand.Parameters.Add(
"#userpic", avatar);
insertCommand.Parameters.Add("#thedate", dt);
insertCommand.Parameters.Add(
"#hash", endhash);
insertCommand.ExecuteNonQuery();
// executes query
}
adapter.Update(data); // saves teh changes
}
reader.Close();
}
}
}
connection.Close();
}
Of course with the additional nesting, parts should be broken out as separate methods.
I suspect your problem is that you're trying to reuse the same SqlCeCommand instances.
Try making a new SqlCeCommand within the while loop. Also, you can use the using statement to close your data objects.
Why are you calling adapter.Update(data) since you're not changing the DataSet at all? I suspect you want to call adapter.Fill(data). The Update method will save any changes in the DataSet to the database.
How to debug programs: http://www.drpaulcarter.com/cs/debug.php
Seriously, can you post some more information about where it's working? Does it work if you use SQL Server Express instead of SQL CE? If so, can you break out SQL Profiler and take a look at the SQL commands being executed?