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();
}
}
Related
namespace ttt
{
public partial class student : Form
{
SqlConnection conn = new SqlConnection(#"Data Source=DESKTOP-R0N4ID3;Initial Catalog=testOnedb;Integrated Security=True");
SqlCommand com;
SqlDataReader read;
public student()
{
InitializeComponent();
com = new SqlCommand("select * from testOnetable",conn);
conn.Open();
com.ExecuteReader();
SqlDataReader read = com.ExecuteReader();
while (read.Read())
{
listBox1.Items.Add("the username : " + read["username"].ToString() + "\n the passward : " + read["passward"].ToString() + "\n the email : " + read["email"].ToString());
}
read.Close();
conn.Close();
}
}
}
You need to wrap the initialization of your database interaction elements (e.g. the SqlConnection and SqlDataReader) in using blocks so the Dispose methods are invoked when you're done with them (or manually do it):
using (SqlCommand com = new SqlCommand("select * from testOnetable", conn))
using (SqlDataReader read = com.ExecuteReader()) {
....
}
Closing the SqlDataReader doesn't dispose of its hold on things (I'm not sure on the technical details in particular for it).
Also, opening a new connection every time you build a new student instance is not nice to the database. You should use a singleton pattern and have a dedicated data access object class.
You have to remove the
com.ExecuteReader();
from your code, that line is useless as you are not assigning the reference to the reader (in the next line you get the reference and assign that correctly in your variable "reader")
Your first call of ExecuteReader() is probably not wanted.
Change
...
conn.Open();
com.ExecuteReader();
SqlDataReader read = com.ExecuteReader();
...
to:
...
conn.Open();
If you intentionally want two readers open simultaneously, set MultipleActiveResultSets=True in your connection string, as explained here: C# Using 2 sqldatareader at same time?
Some other things: You're dealing with disposables here, SqlConnection, SqlCommand and SqlDataReader. You should call Dispose() on them when they are no longer needed of even better wrap a using around them, so that they get disposed automatically.
It's also often a good idea to keep variables as local as possible. It doesn't seem like the connection the command or the reader really need to be members of the class as you only use them in the constructor. Consider pushing them in the constructor all together. Like that you can also use using for disposal of them. Otherwise you had to add and destructor and dispose them there.
public partial class student : Form
{
public student()
{
InitializeComponent();
using (SqlConnection conn = new SqlConnection(#"Data Source=DESKTOP-R0N4ID3;Initial Catalog=testOnedb;Integrated Security=True"))
{
conn.Open();
using (SqlCommand com = new SqlCommand("select * from testOnetable", conn))
{
using (SqlDataReader read = com.ExecuteReader())
{
while (read.Read())
{
listBox1.Items.Add("the username : " + read["username"].ToString() + "\n the passward : " + read["passward"].ToString() + "\n the email : " + read["email"].ToString());
}
read.Close();
}
}
conn.Close();
}
}
private void student_Load(object sender, EventArgs e)
{
}
}
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 :)
My requirement is to read Date column from access file and use one value to append it to a file name, so as to create file with date timestamp using the db value.
I am trying following approach but it gives me exception "No data exists for the row/column":
here's the code
OleDbConnection conn = new OleDbConnection(connectionString);
OleDbConnection conn1 = new OleDbConnection(connectionString);
string dt = "SELECT top 1 Date FROM Events";
OleDbCommand cmd1 = new OleDbCommand(dt, conn1);
conn1.Open();
OleDbDataReader rdr = cmd1.ExecuteReader();
string time_stmp = rdr.GetInt32(0).ToString();
rdr.Close();
conn1.Close();
string path = text_dir + "\\" + time_stmp + "_" + "BWC_Ejournal.txt";
You'll need to call the Read() method on the OleDbDataReader object before accessing its data.
E.g.
OleDbDataReader rdr = cmd1.ExecuteReader();
string time_stmp = "";
if(rdr.Read())
{
time_stmp = rdr.GetInt32(0).ToString();
}
else
{
//handle no data situation here
}
This will also allow to handle a situation where no data is returned more gracefully too.
DATE is a reserved word in ACE/Jet SQL. Try this instead:
string dt = "SELECT TOP 1 [Date] FROM Events";
Edit
On taking a closer look at your code I notice that you create the OleDbCommand object before the connection is opened. I've seen that cause problems as well. FWIW, the following code works for me:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
namespace oleDbTest
{
class Program
{
static void Main(string[] args)
{
using (var con = new OleDbConnection(
"Provider=Microsoft.ACE.OLEDB.12.0;" +
#"Data Source=C:\__tmp\main.accdb;"))
{
con.Open();
using (var cmd = new OleDbCommand(
"SELECT TOP 1 [Date] FROM [Events]", con))
{
string time_stmp = Convert.ToDateTime(cmd.ExecuteScalar()).ToString("yyyyMMdd");
Console.WriteLine(time_stmp.ToString());
}
con.Close();
}
Console.WriteLine("Done.");
System.Threading.Thread.Sleep(2000);
}
}
}
I corrected the spelling mbd to mdb but now the error is
Micorsoft Jet database engine cannot find the input table or query employee make sure it exist and that its name is spelled correctly.
What I want to do is connect to database and extract four fields in the texbox here is my code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
namespace Empdetails
{
public partial class EGUI : Form
{
private OleDbConnection dbConn; // Connectionn object
private OleDbCommand dbCmd; // Command object
private OleDbDataReader dbReader;// Data Reader object
private Emp1 Edetails;
private string sConnection;
private string sql;
public EGUI()
{
InitializeComponent();
}
private void button1_Click(object sender,System.EventArgs e)
{
try
{
// Construct an object of the OleDbConnection
// class to store the connection string
// representing the type of data provider
// (database) and the source (actual db)
sConnection =
"Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=employee.mdb";
dbConn = new OleDbConnection(sConnection);
dbConn.Open();
// Construct an object of the OleDbCommand
// class to hold the SQL query. Tie the
// OleDbCommand object to the OleDbConnection
// object
sql = "Select * From employee";
dbCmd = new OleDbCommand();
dbCmd.CommandText = sql;
dbCmd.Connection = dbConn;
// Create a dbReader object
dbReader = dbCmd.ExecuteReader();
while (dbReader.Read())
{
Edetails = new Emp1
(dbReader["Name"].ToString(), dbReader["Address"].ToString(), dbReader["SocialSecurityNumber"].ToString(), dbReader["Rate"].ToString());
textBox1.Text = dbReader["Name"].ToString();
textBox2.Text = dbReader["Address"].ToString();
textBox3.Text = dbReader["SocialSecurityNumber"].ToString();
textBox4.Text = dbReader["Rate"].ToString();
// tb1.Text = dbReader["FirstName"].ToString();
} // tb2.Text = dbReader["LastName"].ToString();
dbReader.Close();
dbConn.Close();
}
catch (System.Exception ex)
{
MessageBox.Show("exeption" + ex.ToString());
}
}
private void EGUI_Load(object sender, EventArgs e)
{
}
}
Tim and binil are right, you need to provide the full path. I tested your code and it works when you add the full path
try
{
// Construct an object of the OleDbConnection
// class to store the connection string
// representing the type of data provider
// (database) and the source (actual db)
string sConnection =
"Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=C:\\Code\\StackOverflowSamples\\ReadFromAccessDB\\employee.mdb";
using (OleDbConnection dbConn = new OleDbConnection(sConnection))
{
dbConn.Open();
// Construct an object of the OleDbCommand
// class to hold the SQL query. Tie the
// OleDbCommand object to the OleDbConnection
// object
string sql = "Select * From employee";
OleDbCommand dbCmd = new OleDbCommand();
dbCmd.CommandText = sql;
dbCmd.Connection = dbConn;
// Create a dbReader object
using (OleDbDataReader dbReader = dbCmd.ExecuteReader())
{
while (dbReader.Read())
{
Console.WriteLine(dbReader["EmployeeName"].ToString());
Console.WriteLine(dbReader["Address"].ToString());
Console.WriteLine(dbReader["SSN"].ToString());
Console.WriteLine(dbReader["Rate"].ToString());
}
}
}
}
catch (System.Exception ex)
{
Console.WriteLine("exeption" + ex.ToString());
}
Console.ReadLine();
}
Do you need to provide the full path to the file in the connect string?
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;
}
}