Connection must be valid and open error in visual studio - c#

I'm trying to show in my datagridview all the registers from a mariadb database, but when I start the code, it appears the errror "Connection must be valid and open error", the code is Here:
I'll be glad if somebody can help me :)

There are two main problems with your code. Firstly you don't associate your connection object with your command object, instead of
MySqlCommand cmd = new MySqlCommand("SELECT * FROM encomendas");
It should be
MySqlCommand cmd = new MySqlCommand("SELECT * FROM encomendas", bdcon);
Also, there is no need to call cmd.ExecuteNonQuery(). It is also advisable to use using blocks on objects that implement IDisposable to ensure they are disposed of correctly, so your full code might be:
var datatable = new DataTable();
using (var connection = new MySqlConnection("connectionstring"))
using (var command = new MySqlCommand("SELECT * FROM encomendas", connection ))
{
connection.Open()'
using (var reader = command.ExecuteReader())
{
datatable.Load(reader);
}
}
// Bind to your grid view
With that being said, if you are looking to fill a DataTable then MySqlDataAdapater() is the simplest approach:
var dt = new DataTable();
using (var adapter = new MySqlDataAdapter("SELECT * FROM encomendas", "ConnectionString"))
{
adapter.Fill(dt);
}
// Bind to your grid view

Delete MysqlCommand cmd = new MySqlCommand("") row and
try it
using (var sqlCommand = new MySqlCommand("SELECT * FROM encomendas", bdcon))
{
MySqlDataReader read = sqlCommand.ExecuteReader();
dt.Load(read);
}
try it

Your object of MysqlCommand must have association with your object MysqlConnection. Obviously your cmd has no business with bdcon, that is the reason why it says "Connection must be valid and open error" when you call the method ```cmd.ExecuteNonQuery().
Here is a similar snippet.
SqlConnection sqlConnection = new SqlConnection();
SqlCommand cmd = sqlConnection.CreateCommand();
//or
SqlCommand cmd = new SqlCommand("sql text", sqlConnection);

Related

ASP.NET getting data from SQL Server

I am trying to get the name of the employee from the database and fill it in the textbox for the respective employee id.
I tried this code but nothing is happening on the page. It just reloads and the textbox (name) is left blank only.
SqlConnection con = new SqlConnection(#"Data Source=DESKTOP-0FUUV7B\SQLEXPRESS;Initial Catalog=EmployeeDetails;Integrated Security=True");
con.Open();
           
SqlCommand cmd = new SqlCommand("select * from ProfessionalDetails where EmpId='"+EmployeeId.Text+"'", con);
          
SqlDataReader da = cmd.ExecuteReader();
while (da.Read())
{
    Name.Text = da.GetValue(1).ToString();
}
            
con.Close();
Better solution is to execute the sql statement through Parameterized value.
The details of that process is given below:
using (SqlConnection con = new SqlConnection(live_connectionString))
{
using (SqlCommand cmd = new SqlCommand("Query", con))
{
con.Open();
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#EmpId", employeeId);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
var ds = new DataSet();
da.Fill(ds);
string? name = ds.Tables[0].Rows[1]["Variable name"].ToString();
Name.Text =name;
};
}
}
As mentioned above in comments, you have lot of issues.
you should use using with the connection to dispose of them.
You should use parameterized queries to avoid SQL injection.
Put your code in try catch so that you can easily identify the root cause of the issue.
Define the connection string in config file three than defining in the c# code.
You don’t need to select all the columns. And please avoid select * in the query, instead just write your column name, as you want to select only one column here.
You can use ExecuteScalar, it’s used when you are expecting single value.
And first make sure that textbox has the expected value when you are calling this query.
As noted, use paramters, and BETTER use STRONG typed paramters.
And no need to use a dataset, this is a single table - so use a datatable.
thus:
string strSQL =
#"select * from ProfessionalDetails where EmpId= #ID";
using (SqlConnection con = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmd = new SqlCommand(strSQL, con))
{
con.Open();
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = EmployeeID.Text;
DataTable rstData = new DataTable();
rstData.Load(cmd.ExecuteReader());
if (rstData.Rows.Count > 0)
Name.Text = rstData.Rows[0]["Name"].ToString();
}
}

The specified method is not supported

I'm working on a program that shows in a chart in asp.net two columns of a table, so I made a connection to my database (which is correct), the problem is in the metudo (Chart1.DataBindTable) that does not Is working And gives the following error: The specified method is not supported.
I was very grateful if anyone helped me.
The code:
string cs = ConfigurationManager.ConnectionStrings["CS"].ConnectionString;
using (SqlConnection con = new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand("SELECT [Consumo_Medio_Real], [Tipo_de_Fatura] FROM [dbo].[t_faturas] GO", con);
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
Chart1.DataBindTable(rdr, " Consumo_Medio_Real");
Remove that GO from your SQL statement. Your SQL statement should looks like
SELECT [Consumo_Medio_Real], [Tipo_de_Fatura] FROM [dbo].[t_faturas]
Well you are getting error cause the specified column name has space in it as can be seen below
Chart1.DataBindTable(rdr, " Consumo_Medio_Real");
^... Here
It should rather be like below cause the column name represents the X-Axis
Chart1.DataBindTable(rdr, "Consumo_Medio_Real");
See below MSDN link for an example
https://msdn.microsoft.com/en-us/library/dd456766.aspx
Try without "GO"
string cs = ConfigurationManager.ConnectionStrings["CS"].ConnectionString;
using (SqlConnection con = new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand("SELECT [Consumo_Medio_Real], [Tipo_de_Fatura] FROM [dbo].[t_faturas]", con);
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
//Add datatable...
System.Data.DataTable dt = new DataTable();
dt.Load(rdr);
var enumerableTable = (dt as System.ComponentModel.IListSource).GetList();
chart1.DataBindTable(enumerableTable , "X");
And try dumping the data into some objet that implement ienumerable... and pass that as the parameter to .DataBindTable()
look the definition here (the SqlDataReader does not implement IEnumerable)
hope this help!

Error Trying To Fill Data Table

This is my syntax, but I get an error of
The SelectCommand property has not been initialized before calling 'Fill'.
what do I need to do in order to be able to fill the data table?
using (SqlConnection conn = new SqlConnection("Server=Test;Database=Test;Integrated Security=SSPI;"))
{
SqlCommand command = new SqlCommand();
command.CommandText = "SELECT * FROM [dbo].[selfservice] WHERE saleID = #userid;";
command.Parameters.Add("#userid", SqlDbType.VarChar);
command.Parameters["#userid"].Value = row.Field<string>("saleID");
command.Connection = conn;
using (SqlDataAdapter dataadapter1 = new SqlDataAdapter()
{
dataadapter1.Fill(dtData);
}
}
Notice that you're not using the command object. You need to add the select command to your adapter:
using (SqlDataAdapter dataadapter1 = new SqlDataAdapter()
{
dataadapter1.SelectCommand = command
dataadapter1.Fill(dtData);
}
you have to specify select command of SqlDataAdapter before Fill, also you are missing a close parenthesis at the end
using (SqlDataAdapter dataadapter1 = new SqlDataAdapter())
{
dataadapter1.SelectCommand=command;
dataadapter1.Fill(dtData);
}

Retrieving value from sql ExecuteScalar()

I have the following:
String sql = "SELECT * FROM Temp WHERE Temp.collection = '" + Program.collection + "'";
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(sql, conn);
Program.defaultCollection = (String)cmd.ExecuteScalar();
And I want to get the second column after executing the statement. I know it will return only one row with two columns
I have read online that I will have to read each row of the result, is there any other way?
ExecuteScalar gets the first column from the first row of the result set. If you need access to more than that you'll need to take a different approach. Like this:
DataTable dt = new DataTable();
SqlDataAdapater sda = new SqlDataAdapter(sql, conn);
sda.Fill(dt);
Program.defaultCollection = dt.Rows[0]["defaultCollection"];
Now, I realize that the field name may not be defaultCollection, but you can fill that in.
From the MSDN documentation for ExecuteScalar:
Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored.
Now, as a final bit of advice, please wrap all ADO.NET objects in a using statement. Like this:
using (SqlConnection conn = new SqlConnection(connString))
using (SqlDataAdapter sda = new SqlDataAdapter(sql, conn))
{
DataTable dt = new DataTable();
sda.Fill(dt);
// do something with `dt`
}
this will ensure they are properly disposed.
And I want to get the second column after executing the statement
It is not possible with execute scalar.
is there any other way
You have 2 options here either to use SqlDataAdapter or SqlDataReader.
For you using DataReader is a recommended approach as you don't need offline data or do other worh
by using SqlDataAdapter
using (SqlConnection c = new SqlConnection(
youconnectionstring))
{
c.Open();
/
using (SqlDataAdapter a = new SqlDataAdapter(sql, c))
{
DataTable t = new DataTable();
a.Fill(t);
if(t.Rows.Count > 0)
{
string text = t.Rows[0]["yourColumn"].ToString();
}
}
}
by using DataREader
using (SqlConnection connection =
new SqlConnection(connectionString))
{
SqlCommand command =
new SqlCommand(sql, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
//read data here
string text = reader.GetString(1)
}
reader.Close();
}
SqlCommand.ExecuteScalar() can be used only when the result have just one row and one column.
If you need more than one column to be returned, you should use something like this:
String sql = "SELECT * FROM Temp WHERE Temp.collection = '" + Program.collection + "'";
SqlConnection conn = new SqlConnection(connString);
using(SqlCommand cmd = new SqlCommand(sql, conn))
{
using(SqlDataReader rdr = cmd.ExecuteReader())
{
if(rdr.Read())
{
Program.defaultCollection = (String)rdr["Column1"];
Program.someOtherVar = (String)rdr["Column2"];
}
}
rdr.Close();
}
That will be the fastest way.
You can use a DataReader and read only the first column like:
IDataReader cReader = cmd.ExecuteReader();
if(cReader.Read())
{
string cText = cReader.GetString(1); // Second Column
}
ExecuteScalar only returns one value. You have to make sure your query only returns that value.
String sql = "SELECT temp.defaultCollection FROM Temp WHERE Temp.collection = '" + Program.collection + "'";
On a side note, read on SqlParameter. You don't want to concatenate values like that, you'll have a problem when the collection property contains a quote.

Is there a way to have a SqlConnection that will write while an associated DataReader is open?

Or what's the recommended way to read and write at the same time? Having two connections open is the only way? This is on a plain Windows Forms C# (.NET 3.5) app
using (SqlConnection conn = new SqlConnection(connStr)) {
SqlCommand cmdRead = new SqlCommand("select stools from foo", conn);
SqlDataReader rdr = cmdRead.ExecuteReader();
SqlCommand cmdWrite = new SqlCommand("insert into bar values (#beer)", conn);
SqlParameter beer = new SqlParameter("#beer", SqlDbType.Int);
cmdWrite.Parameters.Add(beer);
while(rdr.Read()) {
int stools = rdr.GetInt32(0);
cmdWrite.Parameters["#beer"].value = stools;
//Next line fails for an open data reader associated to the "command"
cmdWrite.ExecuteNonQuery();
}
rdr.Close()
}
This, OTOH, works, but looks ugly to me (besides of opening an extra connection)
using (SqlConnection connR = new SqlConnection(connStr)) {
using (SqlConnection connW = new SqlConnection(connStr)) {
SqlCommand cmdRead = new SqlCommand("select stools from foo", connR);
SqlDataReader rdr = cmdRead.ExecuteReader();
SqlCommand cmdWrite = new
SqlCommand("insert into bar values (#beer)", connW);
SqlParameter beer = new SqlParameter("#beer", SqlDbType.Int);
cmdWrite.Parameters.Add(beer);
while(rdr.Read()) {
int stools = rdr.GetInt32(0);
cmdWrite.Parameters["#beer"].value = stools;
cmdWrite.ExecuteNonQuery();
}
rdr.Close()
}
}
In this simple case, read all the stools, store them in a list, close the reader and then write them will work (as long as there aren't many stools in the database), but in more complex cases it starts being unwieldy and memory hungry, so that's also not desirable.
With SQL 2005 and later, you can use Multiple Active Result Sets (MARS):
http://msdn.microsoft.com/en-us/library/ms345109%28SQL.90%29.aspx
http://msdn.microsoft.com/en-us/library/ms131686.aspx
For this to work, you need to enable it in your connection string.
Why not having two methods: one for reading and one for writing, each using its own connection drawn from the connection pool.
Reading
using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmdRead = new SqlCommand("select stools from foo", conn))
{
conn.Open();
using (SqlDataReader rdr = cmdRead.ExecuteReader())
{
while(rdr.Read())
{
int stools = rdr.GetInt32(0);
}
}
}
Writing
using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmdWrite = new SqlCommand("insert into bar values (#beer)", conn))
{
conn.Open();
SqlParameter beer = new SqlParameter("#beer", SqlDbType.Int);
cmdWrite.Parameters.Add(beer);
cmdWrite.Parameters["#beer"].value = stools;
cmdWrite.ExecuteNonQuery();
}
And then just call them on different threads. This makes methods clearer and more specific.
You can't write while the DataReader is open, creating a second connection is needed in this situation, and IMHO it's not a design issue.
Well the obvious question is why are you doing this in code at all?
You're selecting from one table to write into another - that screams insert query to me.
Doubtless the real world example is more complex in which case you need two connections because datareaders work by holding the connection open 'til you're done and that's more or less that.

Categories