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
Related
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
My thinking is that the problem lies with the adapter. However, I'm still very green and would appreciate any help. I've searched this forum and have had no luck with any of the resolutions I've found (pebkac probably). The application is simple, use textbox input in a parameterized select statement to populate the datagridview. The query will execute but the grid remains empty. VS2017, MySql8.0
private void button2_Click(object sender, EventArgs e)
{
string myConnectionstring = null;
string mySelect = "SELECT * FROM part_data WHERE 'SERIAL' = #test; ";
string tb7 = textBox7.Text;
//Set Connection String And Create Connection
myConnectionstring = "server=localhost;user= admin; database= trace;port=3306;password= admin;Allow User Variables=True";
DataSet ds = new DataSet();
using (MySqlConnection myConnection = new MySqlConnection(myConnectionstring))
{ //Create Command Object
//MySqlCommand myCommand = new MySqlCommand(mySelect, myConnection);
try
{
myConnection.Open();
// myCommand.Prepare();
//myCommand.Parameters.AddWithValue("#test",tb7);
MySqlDataAdapter adapter = new MySqlDataAdapter(mySelect, myConnectionstring);
adapter.SelectCommand.Parameters.AddWithValue("#test",tb7);
//debug to see final select statement
richTextBox1.Text = mySelect;
adapter.Fill(ds);
dataGridView1.DataSource = ds.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show("Query Failed" + ex);
}
}
At first glance it looks as though your query might be bad. Try using backticks around the column name.
SELECT * FROM part_data WHERE `SERIAL` = #test;
Try making the query without parameters, there is no need to do it like that, then try the DataSourceView of your dataset.
I use the following code to fill a DataGridView from an Access Database. After a Save button is clicked if the Data Grid is updated, the Database saves the data.
The strange thing is that this works for 2 out of 3 Data Tables. For the last one it throws an exception:
Syntax error in INSERT INTO statement
public Tables(string tabName)
{
InitializeComponent();
this.Text = tabName;
this.query = string.Format("SELECT *" + " FROM [{0}]", tabName);
conn.Open();
detailTable = new DataTable();
string tableName = tabName;
string query = string.Format("SELECT * FROM [{0}]", tableName);
OleDbDataAdapter detailAdapter = new OleDbDataAdapter(query, conn);
if (detailAdapter != null)
{
detailAdapter.Fill(detailTable);
}
DataGridView.DataSource = detailTable;
conn.Close();
}
private void BtnSave_Click(object sender, EventArgs e)
{
OleDbCommand comm = new OleDbCommand(query, conn);
OleDbDataAdapter adapter = new OleDbDataAdapter(comm);
OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);
adapter.Update(detailTable);
}
Even if the words are reserved keywords (although I searched them) there is no way of that to be the issue.
More information the tabName can be "Partners", "Salaries", "Descriptions" and "Accounts". It doesn't work only on "Partners".
Okay, turns out I was wrong and I apologize for my stubbornness. The problem was in the e-mail column and I did not see why it had a problem with the dash mark.
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();
}
}
}
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.