This is my first time connecting to a database, but i'm having some problems
using Npgsql;
namespace DBPrj
{
class Program
{
static void Main(string[] args)
{
bool boolfound=false;
NpgsqlConnection conn = new NpgsqlConnection("Server=<ip>; Port=5432; User Id=Admin; Password=postgres.1; Database=Test1"); //<ip> is an actual ip address
conn.Open();
NpgsqlCommand cmd = new NpgsqlCommand();
NpgsqlDataReader dr= cmd.ExecuteReader(); //I get InvalidOperationException : The connection is not open.
if (dr.Read())
{
boolfound=true;
Console.WriteLine("connection established");
}
if(boolfound==false)
{
Console.WriteLine("Data does not exist");
}
dr.Close();
conn.Close();
}
}
}
What could be the problem? Is the NpgsqlConnection string written correctly? Could the database be protected from remote access?
How could I fix this problem?
Thanks in advance!
You never assign your NpgsqlConnection to your NpgsqlCommand and you don't supply a query to execute for your NpgsqlDataReader, fixing that should solve the immediate problems.
Also, wrapping at least your NpgsqlConnection in a using()-statement is a good idea to make sure that the connection is always closed, even if there is an exception.
using Npgsql;
namespace DBPrj
{
class Program
{
static void Main(string[] args)
{
bool boolfound=false;
using(NpgsqlConnection conn = new NpgsqlConnection("Server=<ip>; Port=5432; User Id=Admin; Password=postgres.1; Database=Test1"))
{
conn.Open();
NpgsqlCommand cmd = new NpgsqlCommand("SELECT * FROM Table1", conn);
NpgsqlDataReader dr= cmd.ExecuteReader();
if (dr.Read())
{
boolfound=true;
Console.WriteLine("connection established");
}
if(boolfound==false)
{
Console.WriteLine("Data does not exist");
}
dr.Close();
}
}
}
}
In your connection string you may be missing a semi-colon at the end of database.
Database=Test1"
may need to be;
Database=Test1;"
also - it may be worth wrapping your conn.open() in a try catch statement for user-friendliness and ease of catching errors.
Edit 1:
Just did a little reading. Does NpgsqlCommand need parameters to be passed to it? just in pseudo code, something like;
NpgsqlCommand cmd = new NpgsqlCommand(query, conn);
Related
I'm currently working on the login form of a school management system. The thing is that when I try to log in, I get an error:
System.InvalidOperationException: The connection was not closed. The connection's current state is open
It says that the error is on the 30th line of code but I can't seem to find a way to solve it.
Here's the code of the method in which the error occurs:
public void LoginTeacher()
{
try
{
command = new SqlCommand("TeacherLogin", connection);
command.CommandType = CommandType.StoredProcedure;
connection.Open(); // This is the 30th line.
command.Parameters.AddWithValue("#username", Txt_User.Text);
command.Parameters.AddWithValue("#password", Txt_Pass.Text);
SqlDataReader dataReader = command.ExecuteReader();
if (dataReader.Read())
{
TeacherDash teacherDash = new TeacherDash();
this.Hide();
teacherDash.lblusertype.Text = dataReader[1] + " " + dataReader[2].ToString();
teacherDash.ShowDialog();
this.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
connection.Close();
}
}
Immediately after that error is shown there is another one that says:
System.InvalidOperationException: Invalid attempt to call CheckDataIsReady when reader is closed
and points to line 71 which is the following:
public void Login()
{
try
{
command = new SqlCommand("SP_USER_LOGIN", connection);
command.CommandType = CommandType.StoredProcedure;
connection.Open();
command.Parameters.AddWithValue("#user", Txt_User.Text);
command.Parameters.AddWithValue("#pass", Txt_Pass.Text);
SqlDataReader dataReader = command.ExecuteReader();
if (dataReader.Read())
{
LoginTeacher();
if (dataReader[10].Equals("Admin"))
{
AdminDash adminDash = new AdminDash();
this.Hide();
adminDash.lblusertype.Text = dataReader[1] + " " + dataReader[2].ToString();
adminDash.ShowDialog();
this.Close();
}
There's more code after that but I don't find it relevant since it's the same thing but with the different type of users.
Thanks in advance!
You could try changing your TeacherLogin() method to something like the following:
public void TeacherLogin()
{
try
{
using(SqlConnection con = new SqlConnection("connection string"))
{
using(SqlCommand cmd = new SqlCommand("TeacherLogin"))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#username", Txt_User.Text);
cmd.Parameters.AddWithValue("#password", Txt_Pass.Text);
cmd.Connection = con;
con.Open();
using(SqlDataReader dr = cmd.ExecuteReader())
{
while(dr.Read())
{
TeacherDash teacherDash = new TeacherDash();
this.Hide();
teacherDash.lblusertype.Text = string.Format("{0} {1}", dr[1], dr[2]);
teacherDash.ShowDialog();
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
There's no need to use finally{} to close the connection as its all wrapped in a using() block, it will close and dispose on its own when the code leaves the block. I'd always recommend using SQL connections and commands in this way as not doing so can cause issues by leaving connections open.
Database object need to be closed and disposed. Keeping them local to the method where they are used lets you make sure this happens. using blocks take care of this for you.
I used a DataTable instead of testing with the reader because the connection must remain open as long as the reader is in use. Opening and closing the connection in the briefest possible time is important.
Please don't use .AddWithValue. See http://www.dbdelta.com/addwithvalue-is-evil/
and
https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
and another one:
https://dba.stackexchange.com/questions/195937/addwithvalue-performance-and-plan-cache-implications
Here is another
https://andrevdm.blogspot.com/2010/12/parameterised-queriesdont-use.html
Of course you will have to check your database for the real datatypes and field size to have the correct .Add method.
public void LoginTeacher()
{
DataTable dt = new DataTable();
using (SqlConnection cn = new SqlConnection("your connection string"))
using (SqlCommand cmd = new SqlCommand("TeacherLogin", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#username",SqlDbType.VarChar,100 ).Value = Txt_User.Text;
cmd.Parameters.Add("#password",SqlDbType.VarChar, 100 ).Value =Txt_Pass.Text;
cn.Open();
dt.Load(cmd.ExecuteReader());
} //Your connection and command are both disposed
if (dt.Rows.Count > 0)
{
TeacherDash teacherDash = new TeacherDash();
teacherDash.lblusertype.Text = $"{dt.Rows[0][1]} {dt.Rows[0][2]}";
teacherDash.ShowDialog();
Close();
}
else
MessageBox.Show("Sorry, login failed");
}
I am trying to write simple program for console application, but I am facing this error every time.
few months ago this exact code was running fine, but now it is giving me this error,
I reinstalled my visual studio and oracle database, but then also the same error...
Please Help...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Oracle.ManagedDataAccess.Client;
using Oracle.ManagedDataAccess.Types;
namespace dataTestDemo
{
class Program
{
static void Main(string[] args)
{
string constr;
constr = "User Id = hr; Password = tiger; data source = localhost: 1521/ORCL; pooling = false";
try
{
OracleConnection con = new OracleConnection();
con.ConnectionString = constr;
con.open();
OracleCommand cmd = new OracleCommand();
cmd.CommandText = "select salary from employees where employee_id = 109";
OracleDataReader reader = cmd.ExecuteReader();
while (reader.Read())// Here, I am getting this error..
{
Console.WriteLine("Employee Salary = " + reader.GetString(0));
}
con.close();
Console.WriteLine();
Console.WriteLine("Press Enter to continue...");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.InnerException);
Console.WriteLine(ex.Data);
Console.ReadLine();
}
}
}
}
Error:
Operation is not valid due to the current state of the object.
System.Collections.ListDictionaryInternal
enter image description here
I don't see where you are setting your connection on the command object, and you also should open the connection.
OracleConnection con = new OracleConnection();
con.ConnectionString = constr;
// Open the connection
con.Open();
OracleCommand cmd = new OracleCommand();
// Set the connection on the command object
cmd.Connection = connection;
cmd.CommandText = "select salary from employees where employee_id = 109";
OracleDataReader reader = cmd.ExecuteReader();
// Don't forget to close your connection at some point
I purposely left out error checking and assuring the connection is closed after you use it. There is an example at the bottom of the following link that should help you out further.
https://msdn.microsoft.com/en-us/library/system.data.oracleclient.oracleconnection(v=vs.110).aspx
Hope this helps and good luck!
In your code, you create a an object called con which is of type OracleConnection. But after setting the ConnectionString property, you never use this object. My guess is that you need to open the connection and somehow link the cmd object to this connection.
I have the following ridiculously simple code:
static void Main(string[] args)
{
using (OracleConnection conn = new OracleConnection("Data Source=tnsname;User Id=zzzz;Password=xxxx"))
{
using (OracleCommand cmd = new OracleCommand("SELECT * from CONTRACT"))
{
conn.Open();
IDataReader reader = cmd.ExecuteReader();
}
}
}
}
Obviously I've changed the connection string, but if the connection string is wrong, the conn.Open() call fails, so I know the connection string is correct, at least as far as the data source, User Id, and Password.
When it gets to the cmd.ExecuteReader() call, however, I get an InvalidOperationException with the message, Invalid operation. The connection is closed.
I've done a lot of SQL Server stuff from C#, but this is the first time I've used OracleClient. Can't see anything obviously wrong, other than the fact that it's deprecated, but I'd figure it would still function. I'm not trying to write any production code, I'm just trying to do a little one-off test.
You haven't associated your connection object with command.
cmd.Connection = conn;
or pass it in Command constructor like:
using (OracleCommand cmd = new OracleCommand("SELECT * from CONTRACT", conn))
You haven't assigned the Connection instance to the OracleCommand instance
static void Main(string[] args)
{
using (OracleConnection conn = new OracleConnection("Data Source=tnsname;User Id=zzzz;Password=xxxx"))
{
using (OracleCommand cmd = new OracleCommand("SELECT * from CONTRACT", conn))
{
conn.Open();
using(IDataReader reader = cmd.ExecuteReader())
{
.....
}
}
}
}
Just add the conn instance to the constructor of the command.
By the way, also the reader should be enclosed in a using statement
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();
}
}
public class SqlHelper
{
public SqlHelper()
{
}
public static SqlConnection GetConnection()
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = #"Data Source=.\SQLEXPRESS;AttachDbFilename=" + System.Web.HttpContext.Current.Server.MapPath(#"~\App_Data\learn.mdf") + ";Integrated Security=True;User Instance=True";
return conn;
}
public static SqlDataReader ExecuteReader(string sql)
{
SqlConnection con = GetConnection();
con.Open();
SqlCommand cmd = new SqlCommand(sql, con);
SqlDataReader dr = null;
try
{
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
catch
{
con.Close();
return null;
}
return dr;
}
public static Object ExecuteScalar(string sql)
{
SqlConnection con = GetConnection();
con.Open();
SqlCommand cmd = new SqlCommand(sql, con);
Object val = null;
try
{
val = cmd.ExecuteScalar();
}
catch
{
con.Close();
return null;
}
finally
{
con.Close();
}
return val;
}
public static DataSet ExecuteDataSet(string sql)
{
SqlConnection con = GetConnection();
SqlCommand cmd = new SqlCommand(sql, con);
DataSet ds = new DataSet();
SqlDataAdapter adapt = new SqlDataAdapter(cmd);
try
{
adapt.Fill(ds);
}
catch
{
con.Close();
}
return ds;
}
public static void ExecuteNonQuery(string sql)
{
SqlConnection con = GetConnection();
con.Open();
SqlCommand cmd = new SqlCommand(sql, con);
try
{
cmd.ExecuteNonQuery();
}
finally
{
con.Close();
}
}
}
This is the Class which I use to implement every access to my database . But I think that the way I do connection with the database is a little bit overblown cause I have to hit the Connect function every time I need something . As well as other users going to do the same which kills the performance.
So what is the perfect way to connect with the database - and to stay connected if that better . Note that I use the database in many pages!
Thanks
First, you should be using "using" statements to ensure that all your ADO.NET objects are properly disposed of in the event of a failure:
public static void ExecuteNonQuery(string sql)
{
using(var con = GetConnection())
{
con.Open();
using(var cmd = new SqlCommand(sql, con))
{
cmd.ExecuteNonQuery();
}
}
}
However, having said that, I don't really see a problem with this approach. The advantage is that the connections, commands, adapters and whatnot are properly disposed of every time you execute a bit of SQL. If you were to make a single static SqlConnection instance, you'd escalate the chances that the connection is already in use (when, for example, iterating over the contents of a SqlDataReader).
If you are really concerned about it, provide overloads that take a connection as an extra parameter:
public static void ExecuteNonQuery(string sql, SqlConnection connection)
{
using(var cmd = new SqlCommand(sql, con))
{
cmd.ExecuteNonQuery();
}
}
This way, callers can either execute a bit of SQL that doesn't require multiple calls, or they can call your GetConnectionMethod to obtain a connection, and pass it to multiple calls.
If this is used for a web site then you have to consider that between requests for pages, even from the same browser, your server state will be torn down (in general terms) so there's nothing really to be gained from trying to maintain your SQL connection between pages. That's the first thing.
If each page is the result of a single database connection then you are probably as optimised as you really need to be, if you are making several connections over the generation of a page then you may want to look at keeping a connection alive until you have finished retrieving data; either by maintaining the connection or optimising your data retrieval to limit the back and forth between your app and the db.
Maintaining a database connection is the job of the connection pool, and not the connection consumer. The best practice is to aquire a connection as late as possible and release it as soon as possible.
using(var connection = new SqlConnection(YourConnectionStringHelperFunction())
{
}
One thing that YOu might take into consideration is the Dependency Injection PAttern and some IoC controller. If every page needs to have this connection make this an injectable property (constructor probably wont work unless You implement some kind of infrastructure classes like Request) use some container (Unity, Castle, StructureMap) pack the needed things up (maybe cache, maybe some other things) and let the container do the magic (by magic I mean tons of boilerplate code) for You.
luke
First you can write a seperate class like this :
Get method for getting data (with a Select query) and Set method for manipulating data (Insert, Update, Delete)
using System.Data;
using System.Data.Odbc;
using System.Data.SqlClient; //using this you can replace instead odbc to sql
// Example SqlCommand, SqlDataAdapter
class DataBaseConnection
{
private OdbcConnection conn1 = new OdbcConnection(#"FILEDSN=C:/OTPub/Ot.dsn;" + "Uid=sa;" + "Pwd=otdata#123;"); //"DSN=Ot_DataODBC;" + "Uid=sa;" + "Pwd=otdata#123;"
//insert,update,delete
public int SetData(string query)
{
try
{
conn1.Open();
OdbcCommand command = new OdbcCommand(query, conn1);
int rs = command.ExecuteNonQuery();
conn1.Close();
return rs;
}
catch (Exception ex)
{
conn1.Close();
throw ex;
}
}
//select
public System.Data.DataTable GetData(string sql)
{
try
{
conn1.Open();
OdbcDataAdapter adpt = new OdbcDataAdapter(sql, conn1);
DataTable dt = new DataTable();
adpt.Fill(dt);
conn1.Close();
return dt;
}
catch (Exception ex)
{
conn1.Close();
throw ex;
}
}
}
in your form you can make object to that database connection class
DataBaseConnection db = new DataBaseConnection();
now you cal call get set with your get set method as following
string sqlSpecialHoliyday = "SELECT * FROM Holiday WHERE Date_Time='" + selectdate + "' AND IDH='50'";
DataTable dtAdditionalholily = db.GetData(sqlSpecialHoliyday);
AD you can Set Data Using Set method
string insertloginlog = "INSERT INTO Login_Log (Service_No, Machine_Name) VALUES ('" + serviceID + "','" + machiname + "')";
int ret = db.SetData(insertloginlog);
Hope This will help!