Selecting from multiple tables in C# - 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();

Related

C# ASP.NET - SImplify number of SQL queries written in code

Here's a little background on what I'm doing...
I'm writing a C# web app. On the main page, I have a data input form with about 25 individual Dropdownlists. I created a table called options, and it's pretty simple (ID, Category, Option). Each option I create is categorized so my query will only include options that match the category I'm looking up. Each Category matches one of the 25 Dropdownlists I need to populate.
So I'm able to get a few of these populated on the form and they work great. I'm concerned that the re-writing of this code (with slight variation of the DDlist name and category name) will cause the code to be much longer. Is there a way I can create a class of it's own and pass parameters to the class so it only returns me data from the correct category and populates the correct Dropdownlist? Here's some sample code I have so far for 2 DD fields. The DDStationList and DDReqeustType are the names of 2 of the 25 Dropdownlists I have created:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Drawing;
namespace TEST
{
public partial class _Default : Page
{
//Main connection string
string SqlConn = ConfigurationManager.AppSettings["SqlConn"];
string qryRequestType = ConfigurationManager.AppSettings["qryRequestTypes"];
string qryStationNumbers = ConfigurationManager.AppSettings["qryStationNumbers"];
protected void Page_Load(object sender, EventArgs e)
{}
protected void BtnAddNew_Click(object sender, EventArgs e)
{
//GET Request Types
DataTable RequestTypes = new DataTable();
SqlConnection Conn = new SqlConnection(SqlConn);
{
SqlDataAdapter adapter = new SqlDataAdapter(qryRequestType, Conn);
adapter.Fill(RequestTypes);
DDRequestType.DataSource = RequestTypes;
DDRequestType.DataTextField = "Option";
DDRequestType.DataValueField = "Option";
DDRequestType.DataBind();
}
// Get Stations
DataTable Stations = new DataTable();
SqlConnection Conn = new SqlConnection(SqlConn);
{
SqlDataAdapter adapter = new SqlDataAdapter(qryStationNumbers, Conn);
adapter.Fill(Stations);
DDStationList.DataSource = Stations;
DDStationList.DataTextField = "Option";
DDStationList.DataValueField = "Option";
DDStationList.DataBind();
}
}
protected void BtnSubmit_Click(object sender, EventArgs e)
{
//More stuff to do here for submit code
}
}
}
Example queries from my config file that correspond to above code:
SELECT [Option] FROM Table WHERE Category = 'RequestType';
SELECT [Option] FROM Table WHERE Category = 'Station';
So, is it possible I can create a class that I can pass the Option's Category into that runs the query Like this:
SELECT [Option] FROM Table WHERE Category = #Category;
...and then populate the correct Dropdownlist (need to do this 25 times)?
If I'm not clear on my question, I'll be happy to explain further.
Why not create a stored procedure instead?
using (SqlConnection con = new SqlConnection(dc.Con)) {
using (SqlCommand cmd = new SqlCommand("sp_GetCategory", con)) {
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Category", SqlDbType.VarChar).Value = txtCategory.Text;
con.Open();
var results = cmd.ExecuteReader();
}
}
OR include the parameter
string sql = "SELECT [Option] FROM Table WHERE Category = #Category";
using (SqlConnection con = new SqlConnection(dc.Con)) {
using (SqlCommand cmd= new SqlCommand(sql, con)) {
cmd.Parameters.Add("#Category", SqlDbType.VarChar).Value = txtCategory.Text;
con.Open();
var results = cmd.ExecuteReader();
}
}
EDIT
class Category
{
/* properties */
/* method */
public List<Category> GetCategory(string selectedCategory)
{ /* Method statements here */ }
}

Storing Selected CheckedListBox Values in Database

I have two tables in my database. Let's say table A and table B. table A values are put in checkedlistbox. The selected values in checkedlistbox then are put into table B. I tried to make a code however it wont work. Do you have any idea on how to make this problem work?
thanks ahead guys.
by the way im using c#.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Npgsql;
namespace WindowsFormsApplication1
{
public partial class Form8 : Form
{
public Form8()
{
InitializeComponent();
this.Load += Form8_Load;
button2.Click += button2_Click;
}
private void Form8_Load(object sender, EventArgs e)
{
string connstring = ("Server=localhost;Port=5432;User Id=postgres;Password=021393;Database=postgres;");
NpgsqlConnection conn = new NpgsqlConnection(connstring);
NpgsqlCommand cmd = new NpgsqlCommand("SELECT conname FROM condition", conn);
cmd.CommandType = CommandType.Text;
conn.Open();
using (NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd))
{
DataTable dt = new DataTable();
da.Fill(dt);
((ListBox)checkedListBox1).DataSource = dt;
((ListBox)checkedListBox1).DisplayMember = "conname";
((ListBox)checkedListBox1).DisplayMember = "conid";
string[] condition = dt.Rows[0]["conname"].ToString().Split(',');
}
}
private void button2_Click(object sender, EventArgs e)
{
string connstring = ("Server=localhost;Port=5432;User Id=postgres;Password=021393;Database=postgres;");
NpgsqlConnection conn = new NpgsqlConnection(connstring);
NpgsqlCommand cmd = new NpgsqlCommand("Insert into famhistory(famid) Values (#famid)", conn);
conn.Open();
cmd.Parameters.AddWithValue("#famid", checkedListBox1.Text);
cmd.ExecuteNonQuery();
MessageBox.Show("Data has been saved");
conn.Close();
}
}
}
You have to iterate through all the selected items:
//check if any item is selected
if (checkedListBox1.SelectedItems.Count > 0)
{
//connect to database
string connstring = ("Server=localhost;Port=5432;User Id=postgres;Password=021393;Database=postgres;");
NpgsqlConnection conn = new NpgsqlConnection(connstring);
conn.Open();
//loop through all selected items
foreach (object item in checkedListBox1.CheckedItems)
{
//convert item to string
string checkedItem = item.ToString();
//insert item to database
NpgsqlCommand cmd = new NpgsqlCommand("Insert into famhistory(famid) Values (#famid)", conn);
cmd.Parameters.AddWithValue("#famid", checkedItem); //add item
cmd.ExecuteNonQuery();
}
//close connection
conn.Close();
MessageBox.Show("Data has been saved");
}
Note: I am executing all insert commands in one open connection, because opening and closing connection frequently is not best practice.

Specified cast is not valid. Is it because I am attempting to cast an object?

I have the following C# code that I am using to attempt to query an oracle database. I am simply trying to get the numeric result so that I can output it to the console and eventually hold it in a variable.
I keep getting the following error though:
System.InvalidCastException: Specified cast is not valid at Oracle.DataAccess.Client.OracleDataReader.GetInt32(Int32 i)
I am using VS 2012 on a windows professional machine. Please let me know if I need to add additional info. Any help greatly appreciated.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;
using System.Configuration;
using System.Data.SqlClient;
namespace OB_837_File_Reconciliation_Rpt_Automation
{
class Program
{
static void Main(string[] args)
{
OracleConnection dbConnection;
string connectionString = "Data Source=(DESCRIPTION=(ADDRESS= (PROTOCOL=TCP)(HOST=*******)(PORT=******))(CONNECT_DATA=(SERVICE_NAME=******)));User ID=*****;Password=*********";
try
{
dbConnection = new OracleConnection(connectionString);
string query = "select count (*) AS AMG_Prof from wellmed_owner.claim c inner join WELLMED_OWNER.payment_detail pd on c.claim_id = pd.claim_id where c.claim_status in ('6','8','C') and c.insured_group_id in ('ASA','AEP') and c.form_type = '1' and trunc(pd.paid_date) = trunc(sysdate -4)";
dbConnection.Open();
OracleCommand comm = new OracleCommand(query, dbConnection);
OracleDataReader rdr = comm.ExecuteReader();
rdr.Read();
int count = (int)comm.ExecuteScalar();
Console.WriteLine(count);
//int num = rdr.GetInt32(0);
//Console.WriteLine(count);
Console.WriteLine("Connecting Okay");
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
}
use ExecuteScalar
dbConnection.Open();
OracleCommand comm = new OracleCommand(query, dbConnection);
decimal count = (decimal)comm.ExecuteScalar();
Console.WriteLine(count);
Console.WriteLine("Connecting Okay");
Your query returns only one value, therefore use ExecuteScalar instead of ExecuteReader.
Object result = comm.ExecuteScalar ();
if(result != null)
{
decimal count = (decimal) result;
}

Where am I supposed to call the method connection.Open() using 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();

How to read and print out data from mysql in c#

My problem is that I can't print out all the data from the table in my mysql database, I got out just last row in the given table "teacher". is there anyone who can help me find the error?
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 MySql.Data.MySqlClient;
namespace ReadDataFromMysql
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string sql = " SELECT * FROM teacher ";
MySqlConnection con = new MySqlConnection("host=localhost;user=root;password=859694;database=projekt;");
MySqlCommand cmd = new MySqlCommand(sql, con);
con.Open();
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read()) {
data2txt.Text = reader.GetString("id");
datatxt.Text = reader.GetString("userId");
}
}
private void btnclose_Click(object sender, EventArgs e)
{
Close();
}
}
}
Your problem is that you are overwriting data2txt.Text and datatxt.Text on each row of data. if you want to see all of the data in those fields, something like this should do what you need:
data2txt.Text = string.Empty;
datatxt.Text = string.Empty;
while (reader.Read())
{
data2txt.Text += $"{reader.GetString("id")};";
datatxt.Text += $"{reader.GetString("userId")};";
}
You're assigning the value of each field instead of the value of the existing control's text plus the new value. Add a breakpoint to make sure you're getting multiple rows, but as your code is written, you would only see the result of one row in your form because you're overwriting on each iteration through the loop.
This code works.
private void getdata()
{
MySqlConnection connect = new MySqlConnection("SERVER=localhost; user id=root; password=; database=databasename");
MySqlCommand cmd = new MySqlCommand("SELECT ID, name FROM data WHERE ID='" + txtid.Text + "'");
cmd.CommandType = CommandType.Text;
cmd.Connection = connect;
connect.Open();
try
{
MySqlDataReader dr;
dr = cmd.ExecuteReader();
while(dr.Read())
{
txtID.Text = dr.GetString("ID");
txtname.Text = dr.GetString("name");
}
dr.Close();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if(connect.State == ConnectionState.Open)
{
connect.Close();
}
}
Obviously your code shows the last row values of teacher table into your text fields on form.Because your are looping throught the datareader and assigning the values to textfiled.So each iteration it will overwright the previous values in textbox.
You should output the data before again writing in it:
data2txt.Text = reader.GetString("id");
datatxt.Text = reader.GetString("userId");
Or use a var to store all the data in with each 'read' and then output that var
varexample.Text += reader.GetString("id");

Categories