Where am I supposed to call the method connection.Open() using C#? - c#

Hi I am trying to get data from a database shown in a textbox. Doing this I have created three classes: Dal, Controller and TestForm. The thing is that I dont really know where to open the connection nor where to close it. This is what I've done.
In the class Dal I have:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Data.Odbc;
namespace TestingDatabaseConnection
{
class Dal
{
private SqlConnection connection = new SqlConnection();
public SqlConnection GetConnection()
{
if (connection == null)
{
connection.ConnectionString = "Server=Mnemonics-DAT;Database=mem; Integrated Security = true;";
}
return connection;
}
public SqlDataReader GetData()
{
SqlDataReader sqlReads = null;
SqlCommand sqlCommand = new SqlCommand("select * from table_name", GetConnection());
sqlReads = sqlCommand.ExecuteReader();
return sqlReads;
}
}
}
In the class Controller I have:
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestingDatabaseConnection
{
class Controller
{
private Dal dal = new Dal();
public SqlDataReader GetData()
{
return dal.GetData();
}
}
}
and finally in the form:
public partial class TestForm : Form
{
Controller controll;
public TestForm()
{
InitializeComponent();
controll = new Controller();
}
private void showBtn_Click(object sender, EventArgs e)
{
try
{
SqlDataReader sqlReader = controll.GetData();
while (sqlReader.Read())
{
infTxtBox.Text = sqlReader.ToString();
}
}
catch (Exception e1)
{
MessageBox.Show("Something is wrong: " + e1);
}
}
}
The message I get says "Something is wrong: ExecuteReader requires an open and available Connection. The connection's current state is closed.
What I have tried to do to solve the problem(in the class Dal):
Making a property that gets the connection value like this:
public SqlConnection Connect
{
get
{
return connection;
}
}
And then using it in the method GetData():
public SqlDataReader GetData()
{
SqlDataReader sqlReads = null;
try
{
//I call the method Open() here
Connect.Open();
SqlCommand sqlCommand = new SqlCommand("select * from table_name", GetConnection());
sqlReads = sqlCommand.ExecuteReader();
}
catch (Exception e)
{
Console.WriteLine("Error is: " + e);
}
finally
{
//and close it here
Connect.Close();
}
return sqlReads;
}
The error message I get now says: "Something is wrong: Invalid attempt to call Read when reader is closed"
While referring to the class TestForm.

Problem is here:
if (connection == null)
{
connection.ConnectionString = "Server=Mnemonics-DAT;Database=mem; Integrated Security = true;";
}
Your connection can't be null because you initializing it before calling GetConnection method.Instead check your connection string:
if(connection.ConnectionString == "")
{
connection.ConnectionString = "Server=Mnemonics-DAT;Database=mem; Integrated Security = true;";
}
Probably it would better if you use using statements,it will automatically Dispose your Connection object when it's job is done, just define a connection string variable then use:
string connString = "Server=Mnemonics-DAT;Database=mem; Integrated Security = true";
using(var conn = new SqlConnection(connString))
using(var sqlCommand = new SqlCommand("select * from table_name", conn))
{
conn.Open();
sqlReads = sqlCommand.ExecuteReader();
conn.Close();
}

Problem : in Dal class file you are not opening your connection object connection before reading the data.
Solution : You need to Open the SqlConnection object using Open() method before reading the data.
Try This:
public SqlDataReader GetData()
{
SqlDataReader sqlReads = null;
SqlCommand sqlCommand = new SqlCommand("select * from table_name", GetConnection());
connection.Open(); //Open your connection object here.
sqlReads = sqlCommand.ExecuteReader();
return sqlReads;
}

Its because you're trying to read your SqlDataReader on a closed connection.
Do not call connection.close() in your getData() method instead add a method to your Dal class
like so :
public void CloseConnection()
{
connect.close()
}
and then call your closeConnection method after looping trough your DataReader :
SqlDataReader sqlReader = controll.GetData();
while (sqlReader.Read())
{
infTxtBox.Text = sqlReader.ToString();
}
control.CloseConnection();

Related

.NET Core Database The Connection String property has not been initialized

I'm trying to build a .NET 6 Core MVC application that shows a list of user records from the database.
But I'm getting the "The Connection String property has not been initialized" error when trying to open the connection.
Right now I'm trying to give the data in query string but getting this error.
**DATA ACCESS LAYER**
using ABL_USER_DebitCard_Info.Models;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
namespace ABL_USER_DebitCard_Info.Context
{
public class DebitCard_DAL
{
string connectionString = "Data Source = (localdb)\\MSSQLLocalDB; Initial Catalog = ABL_DebitCard_User_Info_DB";
public IEnumerable<Users> GetUserByCNIC(string? CNIC)
{
var debitcardList = new List<Users>();
using (SqlConnection conn = new SqlConnection())
{
SqlCommand cmd = new SqlCommand("ABL_GetUserByCNIC", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#CNIC", CNIC);
conn.Open(); ---> GETTING ERROR HERE
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
var user = new Users();
user.Id = Convert.ToInt32(reader["ID"].ToString);
user.CNIC = reader["CNIC"].ToString();
user.UserName = reader["UserName"].ToString();
user.CardNumber = reader["CardNumber"].ToString();
user.CardStatus = reader["CardStatus"].ToString();
debitcardList.Add(user);
}
conn.Close();
}
return debitcardList;
}
}
}
**Controller**
using ABL_USER_DebitCard_Info.Context;
using ABL_USER_DebitCard_Info.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace ABL_USER_DebitCard_Info.Controllers
{
public class UsersController : Controller
{
DebitCard_DAL dbcontext = new DebitCard_DAL();
[HttpGet]
public ActionResult Details(string CNIC)
{
if(CNIC == null)
{
return NotFound();
}
else
{
List<Users> debitcardList = dbcontext.GetUserByCNIC(CNIC).ToList();
return View(debitcardList);
if(debitcardList.Count == 0)
{
return NotFound();
}
else
{
return View(debitcardList);
}
}
}
}
}
You create the SqlConnection without providing any connection string.
Pass the connection string to the SqlConnection constructor
using (SqlConnection conn = new SqlConnection(connectionString ))
It's good that you have a variable called "connectionString", but don't forget to use it when you need to :)
When making a new instance of your sql connection you forgot to put it.
using (SqlConnection conn = new SqlConnection(connectionStringGoesHere))
connectionstring must mention in the startup.cs
use this or you can use dapper also to run the query in .net core
using (SqlConnection conn = new SqlConnection(connectionString)

Selecting from multiple tables in C#

I am trying to select data from multiple MySQL tables in one simple statement, my problem however is when I try to run it I get the following error:
An exception of type 'System.Exception' occurred in MySql.Data.dll but was not handled in user code
Additional information: No current query in data reader
The code I am using to run the statement is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class RetrieveCars : System.Web.UI.Page
{
String Model;
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
MySql.Data.MySqlClient.MySqlDataReader reader;
String queryStr;
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["model_id"] != null)
{
Model = Request.QueryString["model_id"];
String connString = System.Configuration.ConfigurationManager.ConnectionStrings["WebAppConnString"].ToString();
conn = new MySql.Data.MySqlClient.MySqlConnection(connString);
conn.Open();
queryStr = "";
queryStr = "SELECT c.CarID, c.RegNumber, c.Colour , m.CarModel, m.CarMake, m.CostPerDay FROM car c INNER JOIN model m ON m.ModelID=c.ModelID WHERE c.ModelID = '" + Model + "'";
cmd = new MySql.Data.MySqlClient.MySqlCommand(queryStr, conn);
reader = cmd.ExecuteReader();
reader.Close();
conn.Close();
CarN.Text = reader.GetString(reader.GetOrdinal("CarModel"));
}
}
}
}
You are closing the reader and connection before getting any data. Just move the .Close() calls to the end of the function.
You also need to call Read() on the reader to actually get a row of data.
cmd = new MySql.Data.MySqlClient.MySqlCommand(queryStr, conn);
reader = cmd.ExecuteReader();
// Read() will return a bool indicating whether a new row has been read
// false signals no more data
while (reader.Read()) {
// Do something with the row data
CarN.Text = reader.GetString(reader.GetOrdinal("CarModel"));
}
reader.Close();
conn.Close();

C# Additional information: Connection must be valid and open

I have got some code: THE FULL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using MySql.Data.MySqlClient;
namespace mysql
{
/// <summary>
/// Interaction logic for LoginPage.xaml
/// </summary>
public partial class LoginPage : Page
{
private string conn;
private MySqlConnection connect;
AdminPage ap = new AdminPage();
public LoginPage()
{
InitializeComponent();
}
private void db_connection()
{
try
{
conn = "Server=localhost;Database=student;Uid=root;Pwd=admin;";
connect = new MySqlConnection(conn);
connect.Open();
}
catch (MySqlException e)
{
throw;
}
}
private bool validate_login(string user, string pass)
{
db_connection();
MySqlCommand cmd = new MySqlCommand();
cmd.CommandText = "Select * from student.admins where username=#user and password=#pass";
cmd.Parameters.AddWithValue("#user", user);
cmd.Parameters.AddWithValue("#pass", pass);
cmd.Connection = connect;
MySqlDataReader login = cmd.ExecuteReader();
if (login.Read())
{
connect.Close();
return true;
}
else
{
connect.Close();
return false;
}
}
private void btn_login_Click(object sender, RoutedEventArgs e)
{
string user = txt_admin_name.Text;
string pass = txt_admin_passwd.Password;
if (user == "" || pass == "")
{
//MessageBox.Show("Empty Fields Detected ! Please fill up all the fields");
txt_errormessage.Text = "Empty Fields Detected! Please fill up all the fields!";
return;
}
bool r = validate_login(user, pass);
if (r)
{
//MessageBox.Show("Correct Login Credentials.\n You will be taken the Admin Page!");
this.NavigationService.Navigate(ap);
}
else
//MessageBox.Show("Incorrect Login Credentials");
txt_errormessage.Text = "Incorrect Login Credentials!";
}
}
}
So i need to some error handling: Check the server connection, and check existence of database. I would like to write MessageBox.
I tried but...
"Additional information: Connection must be valid and open."
Thanks in advance!
As soon as you validate the login, you are closing the connection:
if (login.Read())
{
connect.Close();
return true;
}
else
{
connect.Close();
return false;
}
Either leave the connection open, or reopen it. Most people leave it open for speed and simplicity.
When you need to use a connection to a database for every kind of task it is always a good practice to follow the pattern CREATE/OPEN/USE/CLOSE/DISPOSE
So your db_connection code should return the connection created and opened and never use a global variable to keep the connection instance.
private MySqlConnection db_connection()
{
try
{
conn = "Server=localhost;Database=student;Uid=root;Pwd=admin;";
MySqlConnection cnn = new MySqlConnection(conn);
cnn.Open();
return cnn;
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
switch (ex.Number)
{
case 0: MessageBox.Show("Cannot connect to server!"); break;
}
retur null;
}
}
Now the code that want to use your method could be written in a more resource friendly way
private bool validate_login(string user, string pass)
{
using(MySqlConnection cnn = db_connection())
using(MySqlCommand cmd = new cnn.CreateCommand())
{
cmd.CommandText = ".....";
cmd.Parameters.AddWithValue("#user", user);
cmd.Parameters.AddWithValue("#pass", pass);
using(MySqlDataReader login = cmd.ExecuteReader())
return login.HasRows;
}
}
No need to close explicitly the connection because the exit from the using block automatically closes the connection and disposes the instance freeing the resources kept by the connection both locally and on the server.
Of course, when you need to query again the database the same pattern should be used.
You need to tell your command about your connection object. Add the connection parameter to command
MySqlCommand cmd = new MySqlCommand(connect );

Is it safe to use static methods for accessing database in following scenario

I am upgrading a asp website to asp.net. I am trying to follow multi teir approach.
My basic dal layer is as follows which returns a datatable and insert a given query.
using System;
using System.Configuration;
using System.Data;
using MySql.Data.MySqlClient;
public class mydatautility
{
public mydatautility()
{
}
public static DataTable Table(string query)
{
string constr = ConfigurationManager.ConnectionStrings["db_con"].ConnectionString;
DataTable table = new DataTable();
try
{
using (MySqlConnection con = new MySqlConnection(constr))
{
con.Close();
MySqlCommand com = new MySqlCommand(query, con);
MySqlDataAdapter da = new MySqlDataAdapter(com);
con.Open();
da.Fill(table);
con.Close();
da = null;
com = null;
con.Dispose();
}
}
catch (Exception)
{
}
return table;
}
public static int Insert_intoemployee(string query)
{
string constr = ConfigurationManager.ConnectionStrings["db_con"].ConnectionString;
int done = 0;
try
{
using (MySqlConnection con = new MySqlConnection(constr))
{
MySqlCommand com = new MySqlCommand(query, con);
con.Open();
done = com.ExecuteNonQuery();
con.Close();
com = null;
con.Dispose();
}
}
catch (Exception)
{
}
return done;
}
}
I am not sure what will happen when 2 concurrent queries are run.How can I test it for concurrency problem?
There will no concurrency problem as each request has its own thread and static methods have individual call stacks for each thread. However, there are some suggestions in code.
using System;
using System.Configuration;
using System.Data;
using MySql.Data.MySqlClient;
public static class mydatautility//change to Utilities
{
public mydatautility()//not required in this scenario
{
}
public static DataTable Table(string query) //change method name to GetTable
{
string constr = ConfigurationManager.ConnectionStrings["db_con"].ConnectionString;
DataTable table = new DataTable();
try
{
using (MySqlConnection con = new MySqlConnection(constr))
{
con.Close();//not required
using(MySqlCommand com = new MySqlCommand(query, con))
{
MySqlDataAdapter da = new MySqlDataAdapter(com);
con.Open();
da.Fill(table);
con.Close();
da = null;// reduntant, not required
com = null;// reduntant, not required
con.Dispose();// reduntant, not required
}
}
}
catch (Exception)
{
}
return table;
}
public static bool InsertEmployee(string query)// consider changing int to bool since you only require result of operation
{
string constr = ConfigurationManager.ConnectionStrings["db_con"].ConnectionString;
int done = 0;
try
{
using (MySqlConnection con = new MySqlConnection(constr))
{
Using(MySqlCommand com = new MySqlCommand(query, con))
{
con.Open();
done = com.ExecuteNonQuery();
con.Close();
com = null;// reduntant, not required
con.Dispose();// reduntant, not required
}
}
}
catch (Exception)
{
}
return done > 0; // checks rows affected greater than 0
}
}
Using static methods in this scenario is safe. The variables inside the static method is isolated from concurrent calls! see this link too: variable in static methods inside static class
I think it is safe, but bad practice. If you use static methods to access live resource, then how do you want to unit test them? You can not really mock the database access any more.

c sharp return object from function

im facing a problem , when i creat my own class i want to create Mysql connection function and i want to use it inside all my forms i do this
program.cs
using MySql.Data.MySqlClient;
using MySql.Data.Types;
using System.Xml;
using System.IO;
public class testing
{
public string fahadt="Hello Class";
public void conncting()
{
MySqlConnection connection;
string cs = #"server=localhost;userid=root;password=;database=taxi";
connection = new MySqlConnection(cs);
try
{
connection.Open();
}
catch (MySqlException ex)
{
// MessageBox.Show(ex.ToString());
}
}
}
and in my form
private void button7_Click(object sender, EventArgs e)
{
testing fahad = new testing();
try
{
dataGridView1.Show();
fahad.conncting();
// here is error under fahad.conncting.createcommand();
MySqlCommand cmd = fahad.conncting.CreateCommand();
//cmd.CommandText = "SELECT * FROM ocms_visitors WHERE `id`='"+textBox4.Text+"'";
// MySqlDataAdapter adap = new MySqlDataAdapter(cmd);
//textBox4.Text = adap.id;
// DataSet ds = new DataSet();
// adap.Fill(ds);
// dataGridView1.DataSource = ds.Tables[0].DefaultView;
//MessageBox.Show("Yes Mysql Connection is Working Now !");
}
catch (Exception)
{
throw;
}
}
i dont know how i can do it im very new = C#
please help me and also i have another q should i use
using .... in class and form or Enough in class ?
thanks
You need to return MySqlConnection
Modify your function to:
public MySqlConnection conncting()
{
MySqlConnection connection;
string cs = #"server=localhost;userid=root;password=;database=taxi";
connection = new MySqlConnection(cs);
try
{
connection.Open();
return connection;
}
catch (MySqlException ex)
{
return null;
// MessageBox.Show(ex.ToString());
}
}
To answer your initial question, it looks to me like you have already created the connection you were looking for. Next steps for you would be to learn about the SqlCommand Class.
For reference/edification, try this link, and happy coding!
I suspect you want to return a connection from your conncting() method?
public MySqlConnection conncting()
{
string cs = #"server=localhost;userid=root;password=;database=taxi";
MySqlConnection connection = new MySqlConnection(cs);
connection.Open();
return connection;
}
To answer your second question, yes, using using {..} blocks is a good idea for IDisposable instances whenever possible. This includes connections, commands, data adapters, etc. The following might be a reasonable pattern:
using (MySqlConnection conn = fahad.conncting())
using (MySqlCommand cmd = new MySqlCommand("select * from table", conn))
using (MySqlDataAdapter da = new MySqlDataAdapter(cmd))
using (DataTable dt = new DataTable())
{
da.Fill(dt);
// do something with datatable
}

Categories