C#, Access Search through multiple tables for a Serial Number - c#

I have 1 Access database with 2 tables. I am using a C# winforms application. I have Serial Number fields in each table but nothing is related. I have a form with a text field and a button to search for a Serial Number, then will return results into a datagrid on the form. Currently I can simply search 1 table. What I would like to do is type in the number, hit the button and return the value after searching both tables. I would rather do this without a union because somehow I need to set the table name in a text box when the results return.
private void btnSearch_Click(object sender, EventArgs e)
{
OleDbCommand command = new OleDbCommand();
OleDbDataAdapter db = new OleDbDataAdapter(command);
DataTable dt = new DataTable();
if (!string.IsNullOrEmpty(txtSerial.Text))
{
try
{
connection.Open();
command.Connection = connection;
command.Transaction = transaction;
command.Parameters.Add("#searchSerial", OleDbType.VarWChar).Value = txtSerial.Text;
string searchFB = "SELECT (SerialNumber) FROM Inventory WHERE SerialNumber = #searchSerial";
command.CommandText = searchFB;
db.Fill(dt);
dgResults.DataSource = dt;
connection.Close();
}
catch (OleDbException ex)
{
MessageBox.Show(ex.Message);
connection.Close();
}
}
}

Related

Fill combobox with multiple datasets from the same database column at the same time

I have a combobox that is filled from a database conditionally by checking off one of 10 checkboxes. Each of the 10 checkboxes contains the code below, which selects a portion of column based on a value in column2.
private void Check1_CheckedChanged(object sender, EventArgs e)
{
if (Check1.CheckState == CheckState.Checked)
{
// SQL Server connection
SqlConnection conn = new SqlConnection(#"Server = Server; Database = DB; Integrated Security = True");
DataSet ds = new DataSet();
try
{
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT [Column1] FROM [DB].[dbo].[Table1] WHERE [Column2] = 50", conn);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
da.Fill(ds);
combo1.DisplayMember = "Column1";
combo1.ValueMember = "ID";
combo1.DataSource = ds.Tables[0];
}
catch (Exception ex)
{
//Exception Message
}
finally
{
conn.Close();
conn.Dispose();
}
}
if (Check1.CheckState == CheckState.Unchecked)
{
combo1.DataSource = null;
}
Therefore, it is rather trivial to fill the combobox with each separate condition. What I want to do that I'm not sure of the approach, however, is that when more than one checkbox is checked, the combobox will display the data from every checked checkbox at once (all this data will be from the same column). Moreover, when a single checkbox is then unchecked, I only want it to remove its own dataset from the combobox and not everything.
Is this possible?
I think it's possible if you have 1 dataset and then you dynamically build up your SQL query. Set up a variable for the columns you want to return based on all the selected comboBoxes.
Use 1 method for all your after update event on the comboBoxes to make it easier and more maintainable.
In terms of mapping the dynamics columns to the dropdowns, I don't work with Winform so I'm not sure but hope this can help a bit.
You can use the for loop to iterate the values you have retrieved and append the combo box value. Example:
comboBox.Items.Clear(); // <-- Declare this at initialization of the page or whatever scenario you have
private void Check1_CheckedChanged(object sender, EventArgs e)
{
if (Check1.CheckState == CheckState.Checked)
{
// SQL Server connection
SqlConnection conn = new SqlConnection(#"Server = Server; Database = DB; Integrated Security = True");
DataSet ds = new DataSet();
try
{
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT [Column1] FROM [DB].[dbo].[Table1] WHERE [Column2] = 50", conn);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
da.Fill(ds);
// Using loop to iterate the values and append the combo box
for(int i=0;i<da.Rows.Count;i++)
{
combo1.Items.Add(da[i]["Column1"].ToString());
combo1.Items[combo1.Itemx.Count-1].Text=da[i]["Column1"].ToString();
combo1.Items[combo1.Itemx.Count-1].Value=da[i]["Column1"].ToString();
}
}
catch (Exception ex)
{
//Exception Message
}
finally
{
conn.Close();
conn.Dispose();
}
}
if (Check1.CheckState == CheckState.Unchecked)
{
combo1.DataSource = null;
}
This is just an example, hope you can get the idea

Search 2 "unrelated" Access tables with button click

I have 2 tables in an Access database. Currently I have a c# winform app in VS 2015 with 2 forms that have a search button on each that will search that particular table The only similarity is the SerialNumber field but it is unrelated as the Serial Numbers for each table are for different equipment. Any tips on how to perform a search of both tables with 1 button?
private void searchItembtn_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(serialSearch.Text))
{
try
{
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.Transaction = transaction;
command.Parameters.Add("#searchSerial", OleDbType.VarWChar).Value = serialSearch.Text;
string searchFB = "SELECT * FROM Inventory WHERE SerialNumber = #searchSerial";
command.CommandText = searchFB;
connection.Close();
OleDbDataAdapter db = new OleDbDataAdapter(command);
DataTable dt = new DataTable();
db.Fill(dt);
dataGridFB.DataSource = dt;
}
catch (OleDbException ex)
{
MessageBox.Show(ex.Message);
connection.Close();
}
searchHide();
connection.Close();
}
}
Create a UNION query in Access, that will contain data from both tables:
SELECT
SerialNumber,
InventoryField1 AS Field1,
InventoryFieldN AS FieldN
FROM Inventory
UNION ALL
SELECT
SerialNumber,
CompetitiveField1 AS Field1,
CompetitiveFieldN AS FieldN
FROM Competitive
Then use this query as the row source in your command (CompetitiveInventory would be the query name):
string searchFB = "SELECT * FROM CompetitiveInventory WHERE SerialNumber=#searchSerial";
Alternatively, a JOIN may be what you want, depending on the requirement.

OleDbCommand select does not return expected rows

I have two Access tables, namely Projects, including the rows of projectTitle and partyID, and ProjectParty, including the rows of title and ID.
private void btnSearch_Click(object sender, EventArgs e)
{
OleDbConnection conn = new OleDbConnection();
conn.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=HesabKetab.accdb;Persist Security Info=False;";
//search in the database
OleDbCommand oleCmd = new OleDbCommand();
oleCmd.Connection = conn;
if (radioBtnByTitle.Checked)
{
oleCmd.CommandText = "SELECT * FROM Projects WHERE projectTitle=#projectTitle";
oleCmd.Parameters.AddWithValue("#projectTitle", txtProjectTitle.Text);
}
else if (radioBtnByParty.Checked)
{
oleCmd.CommandText = "SELECT * FROM Projects WHERE partyID=#partyID";
oleCmd.Parameters.AddWithValue("#partyID", comboParty.SelectedValue.ToString());
}
//execute query
OleDbDataAdapter ole_da = new OleDbDataAdapter(oleCmd);
DataTable dt= new DataTable();
try
{
conn.Open();
ole_da.Fill(dt);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
dataGridViewDisplaySearchResults.DataSource = dt;
conn.Close();
}
In the above code I am trying to retrieve the values of the Projects Access database table. The second if is successful and it loads the queried rows into DataGridView. But the first if (when true) does not return the expected values. In fact, it loads nothing into the DataGridView. I have no idea why the query does not work when I try to do the select based on projectTitle. I tried debugging but I got no clue which parameters were being passed to the select command. Where am I wrong?
instead txtProjectTitle.ToString() in the first condition, isn't it txtProjectTitle.Text

C# Mysql multiple queries

Im trying to build up a little status-tool. I need to get results of multiple queries (about 4-5). The general connection-setup and 'how-to-read-data' is already done but I cant figure out how the another query executed.
Everything I found while searching for it is for the SqlClient. Im totally overcharged with this.
Here is my code so far (be patient, im a newbie to this):
private void button1_Click(object sender, EventArgs e)
{
if(listView1.Items.Count > 1)
{
listView1.Items.Clear();
}
var listMember = new List<string>{};
var listOnline = new List<string>{};
// SQL PART //
string connString = "Server=10*****;Port=3306;Database=e***;Uid=e***;password=********************;";
MySqlConnection conn = new MySqlConnection(connString);
MySqlCommand command = conn.CreateCommand();
command.CommandText = "SELECT fullname,online FROM member WHERE active = '1' ORDER BY online DESC";
try
{
conn.Open();
}
catch (Exception ex)
{
listView1.Items.Add("Error: " + ex);
}
MySqlDataReader reader = command.ExecuteReader();
while(reader.Read())
{
listMember.Add(reader["fullname"].ToString());
listOnline.Add(reader["online"].ToString());
}
conn.Close();
// SQL ENDING //
// SET ENTRIES TO LISTVIEW //
int counter = 0;
foreach(string member in listMember)
{
ListViewItem item = new ListViewItem(new[] { member, listOnline.ElementAt(counter) });
item.ForeColor = Color.Green;
listView1.Items.Add(item);
counter++;
}
}
Im not really sure how the design/layout will look like in the end, so I would like to just append the results to lists in the sql-part to process the data later out of the lists.
Do I really have to setup a complete new connection after conn.Close()? Or is there any other way? I can just imagine: 5 queries with their own connection,try,catch and 2 loops... this will get about 100-200 lines just for getting the results out of 5 queries. Isnt that a bit too much for such an easy thing?
Hope for some help.
Greetings.
According to the new comments my latest code:
Top:
public partial class Form1 : Form
{
public static string connString = "Server=10****;Port=3306;Database=e****;Uid=e****;password=****;";
public Form1()
{
InitializeComponent();
MySqlConnection conn = new MySqlConnection(connString); // Error gone!
}
Body part:
public void QueryTwoFields(string s, List<string> S1, List<string> S2)
{
try
{
MySqlCommand cmd = conn.CreateCommand(); // ERROR: conn does not exist in the current context.
cmd.CommandType = CommandType.Text;
string command = s;
cmd.CommandText = command;
MySqlDataReader sqlreader = cmd.ExecuteReader();
while (sqlreader.Read())
{
S1.Add(sqlreader[0].ToString());
S2.Add(sqlreader[1].ToString());
}
sqlreader.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void button1_Click(object sender, EventArgs e)
{
if(listView1.Items.Count > 1)
{
listView1.Items.Clear();
}
var listMember = new List<string>{};
var listOnline = new List<string>{};
using (conn) // ERROR: conn does not exist in the current context.
{
conn.Open();
///...1st Query
QueryTwoFields("SELECT fullname,online FROM member WHERE active = '1' ORDER BY online DESC",listMember,listOnline);
//...2nd query
//QueryTwoFields("your new Select Statement", otherList, otherList);
}
}
You don't have to close connection every time you execute one query rarher than close the sqlreader assigned to that connection. Finally when all of your queries have been executed you close the connection. Consider also the use of using:
You cal also define a method for execution your Query in order for your code not to be repetive:
public void QueryTwoFields(string s, List<string> S1, List<string> S2)
///Select into List S1 and List S2 from Database (2 fields)
{
try
{
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
string command = s;
cmd.CommandText = command;
MySqlDataReader sqlreader = cmd.ExecuteReader();
while (sqlreader.Read())
{
S1.Add(sqlreader[0].ToString());
S2.Add(sqlreader[1].ToString());
}
sqlreader.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void button1_Click(object sender, EventArgs e)
{
if(listView1.Items.Count > 1)
{
listView1.Items.Clear();
}
var listMember = new List<string>{};
var listOnline = new List<string>{};
// SQL PART //
using (conn)
{
conn.Open();
///...1st Query
QueryTwoFields("SELECT fullname,online FROM member WHERE active = '1' ORDER BY online DESC",listmember,listonline)
//...2nd query
QueryTwoFields("your new Select Statement",myOtherList1,myOtherlist2)
....
}
}
EDIT :
Take in mind you cant define QueryTwoFields method inside button handler. You must define it outside (see code above).
Also Define your connection data in the start of the programm:
namespace MyProject
{
/// <summary>
/// Defiine your connectionstring and connection
/// </summary>
///
public partial class Form1 : Form
{ public static string connString = "Server=10*****;Port=3306;Database=e***;Uid=e***;password=********************;";
MySqlConnection conn = new MySqlConnection(connString);
.........
Datatables are fantastic
Using a data table is a nice way to do both read and write. And it comes with the luxury of eveything you can do with a datatable - like asssigning it directly to a datagrid control, sorting, selecting and deleting while disconnected.
The sample below assumes a MySqlConnection conection property managed by calls to your own OpenConnection() and CloseConnection() methods not shown.
Simple datatable read demo:
public DataTable Select(string query = "")
{
//Typical sql: "SELECT * FROM motorparameter"
DataTable dt = new DataTable();
//Open connection
if (this.OpenConnection() == true)
{
//Create Command
MySqlCommand cmd = new MySqlCommand(query, connection);
//Create a data reader and Execute the command
MySqlDataReader dataReader = cmd.ExecuteReader();
dt.Load(dataReader);
//close Data Reader
dataReader.Close();
//close Connection
this.CloseConnection();
//return data table
return dt;
}
else
{
return dt;
}
}
In case of writing back the datatable to the database - supply the SQL you used in the read (or would have used to read to the data table):
public void Save(DataTable dt, string DataTableSqlSelect)
{
//Typically "SELECT * FROM motorparameter"
string query = DataTableSqlSelect;
//Open connection
if (this.OpenConnection() == true)
{
//Create Command
MySqlCommand mySqlCmd = new MySqlCommand(query, connection);
MySqlDataAdapter adapter = new MySqlDataAdapter(mySqlCmd);
MySqlCommandBuilder myCB = new MySqlCommandBuilder(adapter);
adapter.UpdateCommand = myCB.GetUpdateCommand();
adapter.Update(dt);
//close Connection
this.CloseConnection();
}
else
{
}
}
The neat thing the datatable is extremely flexible. You can run your own selects against the table once it contains data and before writing back you can set or reset what rows needs updating and by default the datatable keeps track of what rows you update in the table. Do not forget primary key column(s) for all tables in the db.
For multiple queries consider if possible using a join between the database tables or same table if data related or use a UNION sql syntax if column count and type of data is the same. You can allways "create" your extra column in the select to differ what data comes from what part of the UNION.
Also consider using CASE WHEN sql syntax to conditionally select data from different sources.

CombBox is not populating the ValueMember Properly from MySQL in C#

I have two combobox in my form, using a mysql connection to a remote server. The first combobox populated nicely. However, I need the indexid since that is a foreign key to populate a second combobox. Based on the selection, it will change the data in the second combo (for the xample, i the first combo is for car makes, then the models of each make gets filled, so if I choose Nissan, the models will then have Altima, Maxima, Sentra, ... but if I chose Toyota, the combo will then show Corolla, Camry, Prius, ...)
My foreign key is always -1 for some reason. I am using the selectindex change method, but it keeps crashing/ bc the value is always -1.
I am very new to MySQL in C# and eager to learn. Any help is appreciated. The code is below.
private void cboMake_SelectedIndexChanged(object sender, EventArgs e)
{
if (cboMake.SelectedIndex >= 0)
cboModel.Enabled = true;
else
cboModel.Enabled = false;
// get the foreign key value of the model id to get the make for each brand to populate here
// MessageBox.Show(cboModel.ValueMember);
// right now selectindex always shows -1. why?
// if it changes, you need to then enable the right cbo, else, disable.
// but also, you need the mid, fk, so you can then do a new sql statement with the where clause to populate it.
int fk = cboModel.SelectedIndex;
string connStr = "server=123.456.7.8;user=root;database=car;port=3306; password=nowayjose";
MySqlConnection conn = new MySqlConnection(connStr);
try
{
string sql = "SELECT * FROM cs_model WHERE mid='fk'";
MySqlCommand cmd = new MySqlCommand(sql, conn);
DataTable dt = new DataTable();
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
da.Fill(dt);
cboMake.DataSource = dt;
cboMake.DisplayMember = "model";
cboMake.ValueMember = "mmid";
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "MySQL Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
conn.Close();
}
private void frmMain_Load(object sender, EventArgs e)
{
string connStr = "server=123.456.7.8;user=root;database=car;port=3306; password=nowayjose";
MySqlConnection conn = new MySqlConnection(connStr);
try
{
string sql = "SELECT * FROM cs_make";
MySqlCommand cmd = new MySqlCommand(sql, conn);
DataTable dt = new DataTable();
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
da.Fill(dt);
cboMake.DataSource = dt;
cboMake.DisplayMember = "make";
cboMake.ValueMember = "mid";
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "MySQL Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
conn.Close();
}
Correct me if I'm wrong, but considering code provided, just a guess :
private void cboMake_SelectedIndexChanged(object sender, EventArgs e)
{
int fk = cboModel.SelectedIndex; // ?????
.....
}
You access here cboModel, which is not that one whom item was actually selected. At least lookin on event name cboMake_SelectedIndexChanged, seems to me that you should look on cboMake selected index.
Hope this helps.
private void cboMake_SelectedIndexChanged(object sender, EventArgs e)
{
int foreignKey = (int)cboMake.SelectedIndex +1; // i forgot to cast the int from string since the database was tinyint, it still returns string in c#
string fk = foreignKey.ToString(); // since i need the string for the query, back it goes, but i needed to do arithmetic
string connStr = "server=10.18.30.1;user=notroot;database=car;port=3306;password=password";
MySqlConnection conn = new MySqlConnection(connStr);
try
{
string sql = "SELECT * FROM cs_model WHERE mid=" + fk; // forgot to escape out of the string (used to php $var style within double quotes)
MySqlCommand cmd = new MySqlCommand(sql, conn);
DataTable dt = new DataTable();
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
da.Fill(dt);
cboModel.DataSource = dt; // i had cboModel by a silly mistake
cboModel.DisplayMember = "model";
cboModel.ValueMember = "mmid";
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "MySQL Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
conn.Close();
}

Categories