Database is still locked even after disposing commands - c#

Good day I'm currenlty having a problem on my sqlite database in unity using c#.
So far whenever I tried to read my database it works perfectly fine.
But when I try to update it, it always gives me the "Database file is locked" even if there are no commands that are available yet or all commands are disposed and closed.
here is my code:
string conn = "URI=file:" + Application.dataPath + "/Database/SampleDB";
IDbConnection dbconn;
dbconn = (IDbConnection)new SqliteConnection (conn);
dbconn.Open ();
IDbCommand dbcmd = dbconn.CreateCommand();
string sqlQuery = "UPDATE UserScore SET Highscore = '1'";
dbcmd.CommandText = sqlQuery;
IDataReader reader = dbcmd.ExecuteReader();
reader.Close();
reader = null;
dbcmd.Dispose();
dbcmd = null;
dbconn.Close();
dbconn = null;
I use this code in both the reading and updating of the database. I also tried the "using" command
here is the code for reading :
using (SqliteConnection c = new SqliteConnection(conn))
{
c.Open();
using (SqliteCommand cmd = new SqliteCommand(sqlQuery, c))
{
using (SqliteDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
currHighScore = rdr.GetInt32(0);
currHighDist = rdr.GetInt32(1);
Debug.Log( "High Score : " + currHighScore + ", High Distance: " + currHighDist);
}
}
}
}
and here is for updating:
using (SqliteConnection c = new SqliteConnection(conn2))
{
c.Open();
using (SqliteCommand cmd = new SqliteCommand(sqlQuery2, c))
{
if (MoveSanji.scoreAccumulate > currHighScore) {
cmd.ExecuteNonQuery(); //or cmd.ExecuteReader();
}
}
}

SOLVED: Apparently I have to restart Unity. I don't know how and why, but it worked. :) Thanks for the reponse :)

Related

"ExecuteReader:Connection Property has not been initialized."

private void btnSave_Click(object sender, EventArgs e)
{
try
{
con = new SqlConnection("Data Source = LENOVO; Initial Catalog = MainData; Integrated Security = True");
con.Open();
string CheckID = "select StaffID from PersonsData where StaffID='" + txtStaffID.Text + "'";
cm = new SqlCommand(CheckID);
SqlDataReader rdr = null;
rdr = cm.ExecuteReader();
if (rdr.Read())
{
MessageBox.Show("Company Name Already Exists", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
txtStaffID.Text = "";
txtStaffID.Focus();
}
else
{
byte[] img = null;
FileStream fs = new FileStream(imgLoc, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
img = br.ReadBytes((int)fs.Length);
string Query = "insert into PersonsData (StaffID, FullName, Email, Address, Picture) values('" + this.txtStaffID.Text + "','" + this.txtFullname.Text + "','" + this.txtEmail.Text + "','" + this.txtAddress.Text + "',#img)";
if (con.State != ConnectionState.Open)
con.Open();
cm = new SqlCommand(Query, con);
cm.Parameters.Add(new SqlParameter("#img", img));
int x = cm.ExecuteNonQuery();
con.Close();
MessageBox.Show(x.ToString() + "Successfully Saved!");
}
}
catch (Exception ex)
{
con.Close();
MessageBox.Show(ex.Message);
}
}
This is my code i don't understand why I'm getting this error:
ExecuteReader:Connection Property has not been initialized.
I'm making a save button where the Staffid will be checked first if already.
Before executing the command, you need to say which connection is to be used. In your case, it is:
cm.Connection = con;
Take a note that, include this line of code after opening the connection and after creating the instance of SqlCommand.
con = new SqlConnection("Data Source = LENOVO; Initial Catalog = MainData; Integrated Security = True");
con.Open();
string CheckID = "select StaffID from PersonsData where StaffID='" + txtStaffID.Text + "'";
cm = new SqlCommand(CheckID);
cm.Connection = con; //Assign connection to command
You didn't assign connection to SqlCommand used in the reader
The error message is clear enough, You have to assign the connection for the Command, either through assignement or through the constructor, That is:
cm = new SqlCommand(CheckID);
cm.Connection = con; // Should be added
SqlDataReader rdr = cm.ExecuteReader();
Or else you can use the constructor to initialize the command like this:
cm = new SqlCommand(CheckID,con);
Hope that you are aware of these things since you ware used it correctly in the else part of the given snippet
Make sure that you assign the SqlConnection to your Command-Object. You can do this via Constructor or Property:
con = new SqlConnection(//Your Connectionstring)
//assign via Constructor
cm = new SqlCommand(CheckID, con);
//or via Property
cm.Connection = con;
SqlDataReader rdr = null;
rdr = cm.ExecuteReader();
Further I would recommend you to use a using-block to make sure that the Command and Connection gets destroyed after using it.
using (var con = new SqlConnection())
{
using (var cm = new SqlCommand())
{
}
}

C# Windows 8.1 / Get SQLite string query result as variable

How to get the result of this SQLite query result in variable?
I need to access this in my Windows 8.1 application.
string queryDB = string.Format("Select * from ContryLookup");
var tempcountryLookUpData = connection.Execute(queryDB);
Thanks
You will need reference to SqliteDataReader
static void Main()
{
string cs = "URI=file:test.db";
using(SqliteConnection con = new SqliteConnection(cs))
{
con.Open();
string stm = "Select * from ContryLookup";
using (SqliteCommand cmd = new SqliteCommand(stm, con))
{
using (SqliteDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Console.WriteLine(rdr.GetInt32(0) + " "
+ rdr.GetString(1) + " " + rdr.GetInt32(2));
}
}
}
con.Close();
}
}
Credits
Worth mentioning
Do you have an execute procedure called Execute??
One way to do what you want is using the ExecuteReader procedure and return that to a DataReader object. Then use a for loop to traverse the data:
string sql = "select * from table";
SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection);
SQLiteDataReader reader = command.ExecuteReader();
while (reader.Read())
Console.WriteLine(reader["columnName"]);

Connection to database

I am trying to create a class that I can use within my application to easily connect to my database and run queries as needed. I found this post but it is not quite working like I expect.
Here is my class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
//a class that returns a connection to the database
namespace epaCUBE_Utility_Tool
{
public class epaCUBE_DB
{
public static SqlConnection GetConnection()
{
string str = "user id=MyUserName;" +
"password=MyPassword;server=myServer;" +
"database=myDatabase; " +
"connection timeout=30";
SqlConnection con = new SqlConnection(str);
con.Open();
return con;
}
}
}
and here is how I am trying to use it:
private void button1_Click(object sender, EventArgs e)
{
var connection = epaCUBE_DB.GetConnection();
connection.Open();
SqlDataReader rdr = null;
string CommandText = "SELECT Field1, Field2 FROM TableName";
SqlCommand cmd = new SqlCommand(CommandText, connection);
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
this.comboBox1.Items.Add(rdr["Field1"].ToString() +
": " + rdr["Field2"].ToString());
}
connection.Close();
}
when I press the button I get an error
InvalidOperationException: The connection was not closed. The connection's current state is open.
What am I doing wrong?
Thanks,
Leslie
GetConnection calls Open for you, but you're calling it again manually after you called GetConnection. Call it inside GetConnection or outside, but not both places.
Problem is in GetConnection() you already open the connection. All these problems came with your static method.
This is not good way to do this, better to create a new instance of SqlConnection when you need and dispose after use. The underlying connection pooling will be able to manage the physical connections.
separate your UI with Data access, Here you read the data from database and same time adding items to controls. You need to re-factor the code.
You can have method like below to retrieve data
public List<string> GetFields()
{
List<string> fields = new List<string>();
string CommandText = "SELECT Field1, Field2 FROM TableName";
using (var connection = new SqlConnection(epaCUBE_DB.GetConnectionString()))
{
connection.Open();
using (var cmd = new SqlCommand(CommandText, connection))
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
fields.Add(reader["Field1"].ToString() + ": " + reader["Field2"].ToString());
}
}
}
return fields;
}
You're trying to open a connection which is already open, this results in exception.
before opening the connection check the connection status and then open the connection
cmd.Connection.Open();
add the following check/cleanup code:
if (cmd.Connection.State == ConnectionState.Open)
{
cmd.Connection.Close();
}
I program quite defensively; I expect faults to occur and try to handle that gracefully.
As such..
// Define this once in a class and re-use for every connection..
string myConnString = "user id=MyUserName;" +
"password=MyPassword;server=myServer;" +
"database=myDatabase; " +
"connection timeout=30";
using (SqlConnection mySqlConnection = new SqlConnection(myConnString))
{
using (SqlCommand mySQLCommand = new SqlCommand("SELECT Field1, Field2 FROM TableName", mySqlConnection) { CommandType = CommandType.Text})
{
try
{
mySqlConnection.Open();
using (SqlDataReader rdr = mySQLCommand.ExecuteReader())
{
this.comboBox1.Items.Add(rdr["Field1"].ToString() + ": " + rdr["Field2"].ToString());
}
}
catch (Excecption e)
{
// Deal with it as you wish
}
mySqlConnection.Close();
}
}

Error with OracleDataReader. Error: Invalid operation. The connection is closed

When I try to assign the reader C# throws an exception:
Invalid operation. The connection is closed
I try to get a result from a query that returns a single cell with an average value inside.
cmd is an oraclecomand that i use to insert a row into a table and so far so good. I see the message box next and after that the exception appears.
try
{
cmd.ExecuteNonQuery();
MessageBox.Show("Recipe Rated");
OracleCommand cm = new OracleCommand("select round(avg(rating),1) from rates where id_rec = "+id);
OracleDataReader reader = cm.ExecuteReader();
reader.Read();
textBox5.Text =""+reader.GetInt16(0);
}
You should open the connection and you should also use sql-parameters. Hopefully this is the correct oracle syntax because i cannot test it:
using(var con = new OracleConnection("ConnectionString Here"))
using(var cmd = new OracleCommand("ADD YOUR INSERT/UPDATE/DELETE", con))
{
con.Open();
cmd.ExecuteNonQuery();
using (var cm = new OracleCommand("select round(avg(rating),1)As AvgRating from rates where id_rec = #id", con))
{
cm.Parameters.AddWithValue("#id", id);
using (var reader = cm.ExecuteReader())
{
if (reader.Read())
{
textBox5.Text = reader.GetInt16(0).ToString();
}
}
}
}
Note that i have used the using-statement to ensure that all unmanaged resources are disposed as soon as possible. It also closes connections (even on error).
Edit: Since you are selecting just a single value i suggest to use ExecuteScalar:
using (var cm = new OracleCommand("select round(avg(rating),1)As AvgRating from rates where id_rec = #id", con))
{
cm.Parameters.AddWithValue("#id", id);
object avgRating = cm.ExecuteScalar();
if (!(avgRating is DBNull))
{
textBox5.Text = avgRating.ToString();
}
}
When you use `OracleCommand', you have to associate a valid OracleConnection object to it.
using (OracleConnection connection = new OracleConnection(connectionString))
{
MessageBox.Show("Recipe Rated");
OracleCommand cm = new OracleCommand("select round(avg(rating),1) from rates where id_rec = "+id);
try
{
cm.Connection = connection;
connection.Open(); //oracle connection object
OracleDataReader reader = cm.ExecuteReader();
reader.Read();
textBox5.Text =""+reader.GetInt16(0);
}
}
Hope this help.
Thanks.

How do I connect to a database and loop over a recordset in C#?

What's the simplest way to connect and query a database for a set of records in C#?
#Goyuix -- that's excellent for something written from memory.
tested it here -- found the connection wasn't opened. Otherwise very nice.
using System.Data.OleDb;
...
using (OleDbConnection conn = new OleDbConnection())
{
conn.ConnectionString = "Provider=sqloledb;Data Source=yourServername\\yourInstance;Initial Catalog=databaseName;Integrated Security=SSPI;";
using (OleDbCommand cmd = new OleDbCommand())
{
conn.Open();
cmd.Connection = conn;
cmd.CommandText = "Select * from yourTable";
using (OleDbDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
Console.WriteLine(dr["columnName"]);
}
}
}
}
Very roughly and from memory since I don't have code on this laptop:
using (OleDBConnection conn = new OleDbConnection())
{
conn.ConnectionString = "Whatever connection string";
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = conn;
cmd.CommandText = "Select * from CoolTable";
using (OleDbDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
// do something like Console.WriteLine(dr["column name"] as String);
}
}
}
}
That's definitely a good way to do it. But you if you happen to be using a database that supports LINQ to SQL, it can be a lot more fun. It can look something like this:
MyDB db = new MyDB("Data Source=...");
var q = from db.MyTable
select c;
foreach (var c in q)
Console.WriteLine(c.MyField.ToString());
This is an alternative way (DataReader is faster than this one):
string s = "";
SqlConnection conn = new SqlConnection("Server=192.168.1.1;Database=master;Connect Timeout=30;User ID=foobar;Password=raboof;");
SqlDataAdapter da = new SqlDataAdapter("SELECT TOP 5 name, dbid FROM sysdatabases", conn);
DataTable dt = new DataTable();
da.Fill(dt);
for (int i = 0; i < dt.Rows.Count; i++)
{
s += dt.Rows[i]["name"].ToString() + " -- " + dt.Rows[i]["dbid"].ToString() + "\n";
}
MessageBox.Show(s);
If you are intending on reading a large number of columns or records it's also worth caching the ordinals and accessing the strongly-typed methods, e.g.
using (DbDataReader dr = cmd.ExecuteReader()) {
if (dr.Read()) {
int idxColumnName = dr.GetOrdinal("columnName");
int idxSomethingElse = dr.GetOrdinal("somethingElse");
do {
Console.WriteLine(dr.GetString(idxColumnName));
Console.WriteLine(dr.GetInt32(idxSomethingElse));
} while (dr.Read());
}
}
If you are querying a SQL Server database (Version 7 and up) you should replace the OleDb classes with corresponding classes in the System.Data.SqlClient namespace (SqlConnection, SqlCommand and SqlDataReader) as those classes have been optimized to work with SQL Server.
Another thing to note is that you should 'never' select all as this might lead to unexpected results later on if you add or remove columns to this table.
I guess, you can try entity framework.
using (SchoolDBEntities ctx = new SchoolDBEntities())
{
IList<Course> courseList = ctx.GetCoursesByStudentId(1).ToList<Course>();
//do something with courselist here
}
Charge the libraries
using MySql.Data.MySqlClient;
This is the connection:
public static MySqlConnection obtenerconexion()
{
string server = "Server";
string database = "Name_Database";
string Uid = "User";
string pwd = "Password";
MySqlConnection conect = new MySqlConnection("server = " + server + ";" + "database =" + database + ";" + "Uid =" + Uid + ";" + "pwd=" + pwd + ";");
try
{
conect.Open();
return conect;
}
catch (Exception)
{
MessageBox.Show("Error. Ask the administrator", "An error has occurred while trying to connect to the system", MessageBoxButtons.OK, MessageBoxIcon.Error);
return conect;
}
}

Categories