I have written that gets data from a sensor, I am trying to write this data to a local SQL Server database file.
Code doesn't produce any errors but the data is not being written to the data table.
I have used the following code: (any suggestions?)
static void Insert(string date, double value, string deviceName)
{
string path = Directory.GetCurrentDirectory();
string filename = path + "\\Database1.mdf";
Console.WriteLine(filename);
string connectionString = "Data Source=(LocalDB)\\v11.0;AttachDbFilename=" + filename + ";Database=Database1";
using (SqlConnection conn = new SqlConnection(connectionString))
try
{
{
conn.Open();
SqlDataAdapter adapter = new SqlDataAdapter();
using (SqlCommand cmd = new SqlCommand("INSERT INTO DataTable VALUES(#Id, #Date, #Value, #Device Name)", conn))
{
num11 += 1;
cmd.Parameters.AddWithValue("#Id", num11);
cmd.Parameters.AddWithValue("#Date", date);
cmd.Parameters.AddWithValue("#Value", value);
cmd.Parameters.AddWithValue("#Device Name", deviceName);
cmd.ExecuteNonQueryAsync();
//rows number of record got inserted
}
conn.Close();
}
}
catch (SqlException es)
{
Console.WriteLine(es);
//Display Error message
}
}
You're calling ExecuteNonQueryAsync to asynchronously insert the record - but you're then closing the connection immediately, while the insert has almost certainly not yet completed.
You should either use the synchronous call instead, or use asynchrony properly - probably making the method asynchronous, and awaiting the result of ExecuteNonQueryAsync. You need to wait for the operation to complete before you close the connection, basically.
You don't need to call Close explicitly at all, by the way - you've already got a using statement, so the connection will be disposed as execution exits the block. (It's not clear why you've got an extra block inside the using statement either, by the way.)
Related
I am trying to read from a Microsoft Access database with C# with the below code.
static void getProducts()
{
string accessDBPath = #"C:\Users\...\dummydb.accdb";
string connectionString = #"Provider=Microsoft.ACE.OLEDB.16.0;Data Source=" + accessDBPath;
string strSQL = "SELECT * FROM Products";
try
{
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
connection.Open();
OleDbCommand command = new OleDbCommand(strSQL, connection);
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("product name = ...");
}
}
}
catch (OleDbException ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Console.WriteLine("Finished");
}
}
I'm able to walk through the products table just fine (i.e., the stuff inside the while(reader.Read()){...} prints as expected), and the finally block prints as expected as well.
But after the function is done running, the program just never terminates, and the command line just freezes. When I try to force the program to quit at the end of my Main function with Environment.Exit(0);, I get hit with this error:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
The using clause should have automatically closed the database connection when I'm finished with it, but it seemingly behaves as if I hadn't, so I have no clue what's going on, and would appreciate any help.
EDIT: Copy-paste error, declared a variable twice.
I have a post action method which takes in a username and password from a form. In this action method I am using a function to execute a mysql command to a database
This is the function to read from the database
public static MySqlDataReader GetDataFromDB(string command)
{
using (MySqlConnection con = new MySqlConnection(ConStr))
{
com = new MySqlCommand(command, con);
con.Open();
MySqlDataReader rdr1 = com.ExecuteReader();
while (rdr1.Read())
{
}
return rdr1;
}
}
This is how i tried to use this function in my action method
MySqlDataReader rdr2 = Helper.GetDataFromDB("select * from library.Accounts where username = '" + username + "' and password = '" + password + "'");
I put a breakpoint in the helper method and could see that it was reading from the database fine with it storing all the expected row data in the internal 'rdr1' object however it isnt returning anything at the end as the 'rdr2' object is empty once it's finished. I don't know if something is wrong or if im just being an idiot and so i would appretiate if anyone can tell me where im going wrong.
A Data Reader such as MySqlDataReader is Forward Only. This means that once the data has been read and moved on to the next record, or the end of the data, it cannot go back to the beginning.
If you remove this block of code:
while (rdr1.Read())
{
}
You should find it will return the Data Reader at the start, and therefore be able to read the data you loaded from the database.
In addition, you should know that when the using () {...} block finishes the connection will be closed, along with the Data Readers ability to read the data.
If you do want to return the Data Reader, remove the using() {...} block to be a simple statement like:
MySqlConnection con = new MySqlConnection(ConStr);
If you do want to navigate backwards and forwards, filter or sort the data after it has been loaded, you should LOAD the data in to a DataTable from the Data Reader.
Example:
DataTable dt = new DataTable();
dt.Load(rdr1);
This is causing me a headache. I know this question (or atleast variants of it) has been asked many times but before one flags it as a duplicate please consider the following code:
string myConnectionString = myConnectionString = ConfigurationManager.ConnectionStrings["DBCS"].ToString();
SqlConnection mySQLConnection;
SqlCommand mySQLCommand;
SqlDataReader mySQLDataReader;
using (mySQLConnection = new SqlConnection(myConnectionString))
{
mySQLCommand = new SqlCommand("SELECT TOP 1 * FROM Table ORDER BY Id DESC", mySQLConnection);
mySQLCommand.Connection = mySQLConnection;
mySQLCommand.Connection.Open();
using(mySQLDataReader = mySQLCommand.ExecuteReader())
{
if (mySQLDataReader.HasRows)
{
if (mySQLConnection.State == ConnectionState.Open)
{
while (mySQLDataReader.Read())
{
//Perform Logic : If the last record being returned meets some condition then call the below method
MethodCalled();
}
}
}
}
MessageBox.Show("Connection state: " + mySQLConnection.State);
}
I would like to find a way to either:
Close the reader after it has finished reading
Break out of the while-loop when it has finished reading and there are no more rows left
But I just keep on getting a SqlException stating the following:
invalid attempt to call read when reader is closed
Just from broad observation, I can trace that error is due to me returning data that contains one row only. The problem is that after it has read that row, the compiler goes back to While(mySQLDataReader.Read()){} and attempts to read through a table that does not contain any rows.
I attempted the following:
Wrapping the ExecuteReader() from the command object in a using block so that it automatically closes the reader and the connection respectively once it has done reading like so:
using(mySQLDataReader = mySQLCommand.ExecuteReader())
{
//Logic performed
}
Just before the closing brace of the while-loop, I tried checking if there are any more rows left/returned from the sql command and breaking out the loop once that condition is satisfied:
if(mySQLDataReader.HasRows == false) //No more rows left to read
{
break; //break out of loop
}
Both attempts were unsuccessful. How can I get around this?
It must be one of the following 3 things:
You're using Read() OUTSIDE the using block. Remember that using block will implicitly call Close and Dispose on your reader. Thus any Read() calls must be placed inside the using block.
The body of your using block is explicitly closing the reader. This seems improbable.
Apparently you have declared your mySQLDataReader at a higher level. It could be that some other (async) code is closing the reader. This also is unlikely. You shouldn't, in most cases, define a DataReader at global level.
Edit
Reading the full code block that you have posted now, I'd suggest a few changes. Can you run the following and tell us if it runs:
using (var mySQLConnection = new SqlConnection(myConnectionString))
{
mySQLCommand = new SqlCommand("SELECT TOP 1 * FROM Table ORDER BY Id DESC", mySQLConnection, mySQLConnection);
mySQLCommand.Connection.Open();
using(mySQLDataReader = mySQLCommand.ExecuteReader())
{
while (mySQLDataReader.Read())
{
//Perform Logic : If the last record being returned meets some condition then call the below method
MethodCalled();
}
}
}
If this version runs fine, we can then dig the problem better.
If there is no data to iterate, while loop will not execute at all. Do you need to check for HasRows as such? Also, you should use CommandBehavior.CloseConnection when you are creating data reader. This will make sure that underlying connection is closed once you have read through it.
Should if call SqlDataReader.HasRows if I am calling SqlReader.Read
SQLDataReader Source Code
using (SqlConnection mySQLConnection = new SqlConnection(myConnectionString))
{
using (SqlCommand mySQLCommand = new SqlCommand("SELECT TOP 1 * FROM Table ORDER BY Id DESC", mySQLConnection))
{
mySQLConnection.Open();
SqlDataReader mySQLDataReader = mySQLCommand.ExecuteReader(CommandBehavior.CloseConnection);
while (mySQLDataReader.Read())
{
//Code logic here
}
// this call to mySQLDataReader.Close(); will close the underlying connection
mySQLDataReader.Close();
}
MessageBox.Show("Connection state: " + mySQLConnection.State);
}
I've written a function to perform MySQL statements. In this function I give in a statement and get back the MySqlDataReader, but the problem is my function do not close the connection. After a short while of using the Programm, it crashs because the new connection can't be open. This is the error i got by trying open the new connection:
error connecting: Timeout expired. The timeout period elapsed prior
to obtaining a connection from the pool. This may have occurred
because all pooled connections were in use and max pool size was
reached.
My code look like this:
MySQL Class:
class mySql
{
string cs = "server=123.123.123.123;" +
"uid=abcabc;" +
"pwd=123456;" +
"database=overflow_test;";
private MySqlConnection conn_f() // create a Connection
{
MySql.Data.MySqlClient.MySqlConnection conn;
conn = new MySql.Data.MySqlClient.MySqlConnection();
conn.ConnectionString = cs;
try
{
conn.Open();
return conn;
}
catch
{
return null;
}
}
public MySqlDataReader CMD_f(string comand) //execute SQL Command
{
MySql.Data.MySqlClient.MySqlCommand cmd;
cmd = new MySql.Data.MySqlClient.MySqlCommand();
MySqlConnection conn = conn_f();
cmd.Connection = conn;
cmd.CommandText = comand;
cmd.Prepare();
rdr = cmd.ExecuteReader();
return rdr;
}
}
and an example how i use it Main Class
class main{
mySql DB = new mySql();
public void main(){
MySqlDataReader rdr = DB.CMD_f("SELECT * FROM tbl_kategorie");
int i = 0;
while (rdr.Read())
{
string str = rdr.GetString(1);
Console.WriteLine(str);
}
}
Has someone an Idea to solve the Problem.
Sincere regards LFS96 (Fabian Harmsen)
The main problem is the inbalance in the code. The CMD_f method creates a connection, but doesn't take responsibility for it. You should rather make the method that creates the connection public, so that you can take responsibility for it in the code that can close it.
That's a bigger change, so first let's look at a smaller change to fix the code.
The data reader should expose the data connection as the Connection property. I don't see that in the documentation, so it's possible that it doesn't, but the data readers in the .NET framework does.
If the property is exposed, then you can make a quick fix to make the code work with minimal change:
MySqlDataReader rdr = DB.CMD_f("SELECT * FROM tbl_kategorie");
int i = 0;
while (rdr.Read())
{
string str = rdr.GetString(1);
Console.WriteLine(str);
}
rdr.Close();
rdr.Connection.Close();
If you make the conn_f method public and don't call it in the CMD_f method, you can write much more robust code, that never leaves a connection or data reader hanging even if there is an error. That's a bigger change in the code, but definitely worth the effort when you have time to implement and test it. Using a using block to make sure that the objects are always disposed correctly makes the code much more resilient:
using (MySqlConnection conn = DB.conn_f()) {
using (MySqlDataReader rdr = DB.CMD_f(conn, "SELECT * FROM tbl_kategorie")) {
int i = 0;
while (rdr.Read()) {
string str = rdr.GetString(1);
Console.WriteLine(str);
}
}
}
Side note: Identifiers in C# tend to be descriptive. I suggest names like DB.CreateConnection and DB.ExecuteReader rather than DB.conn_f and DB.CMD_f.
I have a method that allows me to kick off a back up of a data base. What I am wondering is if I should be using ExecuteNonQuery() in this context or if there is something better to use. Here is my code currently:
public static void RunBackup(string dbName, string filePath, string backupName, string connString)
{
using(SqlConnection objConnection = new SqlConnection(connString))
{
string commmandText = "BACKUP DATABASE #DBName TO DISK = #FilePath WITH NOFORMAT, NOINIT, NAME = #BackUpName, SKIP, NOREWIND, NOUNLOAD, STATS = 10";
SqlCommand objCommand = new SqlCommand(commmandText,objConnection);
objCommand.Parameters.AddWithValue("#dbName", dbName);
objCommand.Parameters.AddWithValue("#FilePath", filePath);
objCommand.Parameters.AddWithValue("#BackUpName", backupName);
objConnection.Open();
objCommand.ExecuteNonQuery();
objConnection.Close();
}
}
The one thing I am concerned about is being able to verify that the backup is complete and successful while handling time out issues for backups that take and extended time to complete.
ExecuteNonQuery means that the command doesn't return any data. It doesn't mean that it executes asynchronously or that you won't receive error information. It will block until the command finishes and return any errors that may occur
To handle the issue of the long running query I ended up going with this:
public static void RunBackup(string dbName, string filePath, string backupName, string connString)
{
string commmandText = "BACKUP DATABASE #DBName TO DISK = #FilePath WITH NOFORMAT, NOINIT, NAME = #BackUpName, SKIP, NOREWIND, NOUNLOAD, STATS = 10";
SqlConnection objConnection = new SqlConnection(connString);
try
{
SqlCommand objCommand = new SqlCommand(commmandText, objConnection);
objCommand.Parameters.AddWithValue("#dbName", dbName);
objCommand.Parameters.AddWithValue("#FilePath", filePath);
objCommand.Parameters.AddWithValue("#BackUpName", backupName);
objConnection.Open();
IAsyncResult result = objCommand.BeginExecuteNonQuery();
while (!result.IsCompleted)
{
System.Threading.Thread.Sleep(100);
}
int count = objCommand.EndExecuteNonQuery(result);
}
catch (SqlException e)
{
throw e;
}
finally
{
objConnection.Close();
}
}
This will allow me to execute the command without asyncronously without timeout issues. I will be adding some additional error handling etc in my final code set. I may do some additional work to see if I can get a better status returned at the end of the script that I can get via EndExecuteNonQuery or through an AsyncCallBack.
ExecuteNonQuery()
should be fine to use here. What I would do is run a try catch around the using to catch any errors that might happen and deal with them appropiately.
You should use ExecuteNonQuery when you do not what to receive any information from the database as a result of your call. If any error with happen during execute of the command you will get a corresponding exception.
This does look like the type of thing you should put in a stored procedure to do some error handling.
Also, have a look here to see it done in code.
I think ExecuteNonQuery is fine, but You should consider to user a timeout with Your query.
objCommand.CommandTimeout = 60*60; // for an hour or more
If You're using a desktop application, then for sure You should execute this query within asynchronous call.
ExecuteNonQuery is the correct command to use.
If you wish to receive more info about the restore process you should subscribe to the InfoMessage event of the SqlConnection object. That was you can capture all the "non-error" messages as well.
Try it. it resolved timeout expired problem while large size db.
Private Sub Command1_Click()
On Error Resume Next
Dim con As New Connection
Dim tm As String
con.CommandTimeout = 500'''Command timeout should be 500
With con
.ConnectionString = "Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=dbiBMS;Data Source=192.168.103.4"
.Open
End With
tm = CStr(Time)
con.Execute " backup database dbiBMS to disk='E:\Database_Backup\Test1.bak' with format "
con.Close
MsgBox tm
Exit Sub
x:
MsgBox Err.Description
End Sub