I am developing a system that is to have GridView with a select option to select the data stored in a particular row by its primary key ID.
This code works just fine on another page to perform the exact same functionality
protected void lnk_OnClick(object sender, EventArgs e)
{
int objectiveID = Convert.ToInt32((sender as LinkButton).CommandArgument);
if (con.State == ConnectionState.Closed)
con.Open();
SqlDataAdapter sqlDa = new SqlDataAdapter("objectiveViewByID", con);
sqlDa.SelectCommand.CommandType = CommandType.StoredProcedure;
sqlDa.SelectCommand.Parameters.AddWithValue("#objectiveID", objectiveID);
DataTable dtbl = new DataTable();
sqlDa.Fill(dtbl);
con.Close();
hfobjectiveID.Value = objectiveID.ToString();
txtAudience.Text = dtbl.Rows[0]["audience"].ToString();
txtCondition.Text = dtbl.Rows[0]["condition"].ToString();
txtBloom.Text = dtbl.Rows[0]["bloom_level"].ToString();
txtVerb.Text = dtbl.Rows[0]["verb"].ToString();
txtProduct.Text = dtbl.Rows[0]["product"].ToString();
btnSave.Text = "Update";
btnDelete.Enabled = true;
}
I expect the code to repopulate the input fields that were used to populate the database.
In theory, a format exception, it could give an error here if the ToInt32 method input is some non number value.
int objectiveID = Convert.ToInt32((sender as LinkButton).CommandArgument);
Other potential areas are the following code, if the value, for instance, dtbl.Rows[0]["audience"] is null.
But that would be a different exception though. You could put a break point at the top and see which line crashing.
hfobjectiveID.Value = objectiveID.ToString();
txtAudience.Text = dtbl.Rows[0]["audience"].ToString();
txtCondition.Text = dtbl.Rows[0]["condition"].ToString();
txtBloom.Text = dtbl.Rows[0]["bloom_level"].ToString();
txtVerb.Text = dtbl.Rows[0]["verb"].ToString();
txtProduct.Text = dtbl.Rows[0]["product"].ToString();
Related
I am creating an airline booking system and I have 2 combo boxes. The first is for Departure City and the second is for Arrival City. I want to be able to eliminate the choice in the first combo box from the second, as I don't want the same city to be able to be submitted as both the departure and arrival city. I am querying the city names from a database.
Here is my code:
public partial class main : Form
{
public main()
{
InitializeComponent();
string connectionString = #"Base Schema Name=cyanair;data source=C:\Users\Client 0819\source\repos\Cyanair\cyanair.db";
//Departure ComboBox
SQLiteConnection conn = new SQLiteConnection(connectionString);
try
{
conn.Open();
SQLiteCommand cmd = new SQLiteCommand();
cmd.Connection = conn;
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "SELECT * FROM CyanairAirports";
SQLiteDataAdapter da = new SQLiteDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
comboDeparture.DataSource = dt;
comboDeparture.ValueMember = "Descriptions";
comboDeparture.DisplayMember = "Descriptions";
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//Arrival ComboBox
private void comboDeparture_DisplayMemberChanged(object sender, EventArgs e)
{
string connectionString = #"Base Schema Name=cyanair;data source=C:\Users\Client 0819\source\repos\Cyanair\cyanair.db";
SQLiteConnection conn = new SQLiteConnection(connectionString);
**String city = comboDeparture.DisplayMember;**
try
{
conn.Open();
SQLiteCommand cmd = new SQLiteCommand();
cmd.Connection = conn;
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "SELECT * FROM CyanairAirports WHERE Descriptions IS NOT '" + comboDeparture.SelectedValue.ToString() + "'";
richTextBox1.Text = "SELECT * FROM CyanairAirports WHERE Descriptions IS NOT '" + comboDeparture.SelectedValue + "'";
SQLiteDataAdapter da = new SQLiteDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
comboArrival.DataSource = dt;
comboArrival.ValueMember = "Descriptions";
comboArrival.DisplayMember = "Descriptions";
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Thanks :)
It looks like you're handling the DisplayMemberChanged event on comboDeparture, and trying to update the values of comboArrival in that handler. However, DisplayMemberChanged only triggers when the DisplayMember property changes.
DisplayMember only tells the control which property to display on a data bound control. It isn't tied to the index or value selected in the ComboBox. So, the only time the code to populate comboArrival runs is in the constructor when you set comboDepartarture.DisplayMember. Instead, handle either ComboBox.SelectedIndexChanged or ComboBox.SelectedValueChanged and set the items of comboArrival.
A few other important things to note about your code.
First, you should use a parameterized query when running Sql Statements, rather than concatenating strings. Concatenating strings as you're doing opens you up to SQL Injection Attacks. I'm not familiar with SqlLite and can't provide you with an example of how to modify your code, but perhaps this question can help.
Second, you don't need to re-run the query every time you change the selected value in comboDeparture. Just add comboArrival's data source as a field on the Form and you can filter it. For example...
public partial class main : Form
{
// Your constructors...
private void comboDepartures_SelectedIndexChanged(object sender, EventArgs e)
{
if (_arrivalsDataSource == null)
{
_arrivalsDataSource = new System.Data.DataTable();
// Load _arrivalsDataSource from the database, basically how you're doing it now.
comboArrival.DataSource = _arrivalsDataSource.DefaultView;
comboArrival.DisplayMember = "Descriptions"
comboArribal.ValueMember = "Descriptions"
}
if (comboDeparture.SelectedIndex == -1)
{
_arrivalsDataSource.DefaultView.RowFilter = null; // Clear the filter.
}
else
{
// Set the filter.
_arrivalsDataSource.DefaultView.RowFilter = $"Description <> '{comboDeparture.SelectedValue}'";
}
}
private System.Data.DataTable _arrivalsDataSource = null;
}
I have a Textbox with which I want to be able to Search and Insert data into Table. Insert works fine with one exception: When I try to Insert data that isn't already in DB(it's searching while I'm typing) it gives me:
"Exception User-Unhandled System.NullReferenceException: 'Object
reference not set to an instance of an object.'
System.Windows.Forms.DataGridView.CurrentRow.get returned null.
I think I'm missing something in the Search code.
//UPDATE: All of the code.// This is my Insert and Search code:
namespace UDDKT
{
public partial class FrmGlavna : Form
{
DataSet ds = new DataSet();
SqlDataAdapter DaDavaoci = new SqlDataAdapter();
SqlDataAdapter DaAkcije = new SqlDataAdapter();
SqlConnection cs = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\UDDKT.mdf;Integrated Security=True");
public FrmGlavna()
{
InitializeComponent();
}
//Popunjava DataGridViews sa podacima iz baze
private void FrmGlavna_Load(object sender, EventArgs e)
{
SqlCommand SlctDavaoci = new SqlCommand("SELECT * FROM Davaoci ORDER BY DavaocID DESC", cs);
DaDavaoci.SelectCommand = SlctDavaoci;
DaDavaoci.Fill(ds, "TblDavaoci");
SqlCommand SlctAkcije = new SqlCommand("SELECT * FROM AkcijaDDK", cs);
DaAkcije.SelectCommand = SlctAkcije;
DaAkcije.Fill(ds, "TblAkcije");
DgDavaoci.DataSource = ds.Tables["TblDavaoci"];
}
//Povezuje DataGridViews Davaoca i Akcija
private void DgDavaoci_SelectionChanged(object sender, EventArgs e)
{
ds.Tables["TblAkcije"].DefaultView.RowFilter = "DavaocID =" + DgDavaoci.CurrentRow.Cells["DavaocID"].Value;
DgAkcije.DataSource = ds.Tables["TblAkcije"];
}
//Osvježava DataGridView nakon unosa/izmjene/brisanja podataka u bazu
private void RefreshTable()
{
SqlConnection cs = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\UDDKT.mdf;Integrated Security=True");
String query = "SELECT * FROM Davaoci ORDER BY DavaocID DESC";
SqlCommand cmd = new SqlCommand(query, cs);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
DgDavaoci.DataSource = dt;
}
//Čisti TextBox nakon upisa/izmjene/brisanja podataka u bazu
public void ClearTxtBx()
{
TxtIme.Clear();
TxtPrezime.Clear();
TxtTezina.Clear();
TxtAdresa.Clear();
TxtBrojTel.Clear();
TxtBrojLK.Clear();
}
//Upis podataka u Tabelu Davaoci
private void BtnDodajDavaoca_Click(object sender, EventArgs e)
{
String query = "INSERT INTO Davaoci (Ime,Prezime,Pol,DatumRodjenja,KrvnaGrupa,Tezina,Adresa,BrojTel,BrojLK) VALUES (#Ime, #Prezime, #Pol, #DatumRodjenja, #KrvnaGrupa, #Tezina, #Adresa, #BrojTel, #BrojLK)";
using (SqlConnection cs = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\UDDKT.mdf;Integrated Security=True"))
using (SqlCommand command = new SqlCommand(query, cs))
{
command.Parameters.Add("#Ime", SqlDbType.NVarChar).Value = TxtIme.Text;
command.Parameters.Add("#Prezime", SqlDbType.NVarChar).Value = TxtPrezime.Text;
command.Parameters.Add("#Pol", SqlDbType.NChar).Value = TxtPol.Text;
command.Parameters.Add("#DatumRodjenja", SqlDbType.Date).Value = TxtDatumRodjenja.Text;
command.Parameters.Add("#KrvnaGrupa", SqlDbType.VarChar).Value = TxtKrvnaGrupa.Text;
command.Parameters.Add("#Tezina", SqlDbType.Float).Value = TxtTezina.Text;
command.Parameters.Add("#Adresa", SqlDbType.NVarChar).Value = TxtAdresa.Text;
command.Parameters.Add("#BrojTel", SqlDbType.NVarChar).Value = TxtBrojTel.Text;
command.Parameters.Add("#BrojLK", SqlDbType.NVarChar).Value = TxtBrojLK.Text;
cs.Open();
command.ExecuteNonQuery();
cs.Close();
RefreshTable();
ClearTxtBx();
}
}
//Pretraga postojećih Davalaca
private void TxtIme_TextChanged(object sender, EventArgs e)
{
(DgDavaoci.DataSource as DataTable).DefaultView.RowFilter = string.Format("Ime LIKE '{0}%'", TxtIme.Text);
}
}
}
}
Here is the MockUp of the Form before I begin to type/search/insert Data that isn't already in the Table (First Textbox*).
And after I start typing Name(Име) that starts with an "A" (name that isn't already in the Table).
I want to Search DB for that Column, but if there aren't any existing names, I want to be able to continue typing (without interuption) so that I can Insert new data into table.
DgDavaoci.CurrentRow in your DgDavaoci_SelectionChanged method is null, so attempting to access DgDavaoci.CurrentRow.Cells["DavaocID"] throws the NullReferenceException. The reason, best I can tell, is as follows:
You begin to type a value into your text box, a value that happens not to be found in the data set. As you type, you cause the TxtIme_TextChanged method to execute. It filters according to your search, and since the value is not found, it filters out every row in the set. Here's the important part: whenever the data set is filtered, it has the possibility of causing DgDavaoci_SelectionChanged to execute. Since the selection changed from the first row to no row at all (since there are no filtered rows to display), this method does execute. Now, when the method attempts to access the current row, there is no current row, and so we get a null here. Attempting to access a field of null throws the exception you're getting.
How can you fix this behavior? A simple null-check in DgDavaoci_SelectionChanged should do the trick. It looks to me like you can simply return from that method if(DgDavaoci.CurrentRow == null), or you can code in additional behavior. Just perform a check so that you don't reference the null object.
Probably the filter inside TxtIme_TextChanged is causing the DataGridView's SelectionChanged event to fire and the code is entering DgDavaoci_SelectionChanged. The exception indicates that DgDavaoci.CurrentRow is null, so you'll need to handle the case where DgDavaoci.CurrentRow is null in DgDavaoci_SelectionChanged.
A simple way to deal with this would be to just check DgDavaoci.CurrentRow is null and return from the function if that evaluates to true.
private void DgDavaoci_SelectionChanged(object sender, EventArgs e)
{
if (DgDavaoci.CurrentRow is null)
{
return;
}
ds.Tables["TblAkcije"].DefaultView.RowFilter = "DavaocID =" +
DgDavaoci.CurrentRow.Cells["DavaocID"].Value;
DgAkcije.DataSource = ds.Tables["TblAkcije"];
}
It looks like you might have a second DataGridView (DgAkcije) that is designed to show the details of the currently selected row in DgDavaoci. So, another approach might be to just clear DgAkcije if DgDavaoci.CurrentRow is null.
private void DgDavaoci_SelectionChanged(object sender, EventArgs e)
{
if (DgDavaoci.CurrentRow is null)
{
DgAkcije.DataSource = null; //I'm not 100% sure this will work, I haven't tested it.
return;
}
ds.Tables["TblAkcije"].DefaultView.RowFilter = "DavaocID =" +
DgDavaoci.CurrentRow.Cells["DavaocID"].Value;
DgAkcije.DataSource = ds.Tables["TblAkcije"];
}
Ultimately, however, you'll have to decide what you want to happen when DgDavaoci_SelectionChanged is called but DgDavaoci.CurrentRow is null.
Solution if anyone else is interested:
//Povezuje DataGridViews Davaoca i Akcija
private void DgDavaoci_SelectionChanged(object sender, EventArgs e)
{
if (DgDavaoci.CurrentRow != null)
{
ds.Tables["TblAkcije"].DefaultView.RowFilter = "DavaocID =" + DgDavaoci.CurrentRow.Cells["DavaocID"].Value;
DgAkcije.DataSource = ds.Tables["TblAkcije"];
}
}
Originally I was using a Listview to display the oracle results however I've recently had to switch to a datagridview to work with the results a bit more than the Listview allows. Since switching to a datagrid however I am getting less results. I've been stepping through the code and haven't been able to determine where the problem occurs.
This is frmMain where I display the results.
private void button1_Click(object sender, EventArgs e)
{
dtpicker.Format = DateTimePickerFormat.Custom;
dtpicker.CustomFormat = "dd-MMM-yy";
string VoidDate = dtpicker.Text.Trim().ToUpper();
DataTable resultnew = new DataTable();
resultnew.Load(oracleConnection.GetVoidDGV(VoidDate));
if (resultnew != null)
{
dataGridView1.DataSource = DBNull.Value;
dataGridView1.Columns.Clear();
dataGridView1.DataSource = resultnew;
SetupDGV();
}
else
{
MessageBox.Show("No History Found");
}
}
private void SetupDGV()
{
dataGridView1.Columns[0].HeaderText = "Heat Run";
dataGridView1.Columns[1].HeaderText = "Lot Number";
dataGridView1.Columns[2].HeaderText = "Serial Number";
dataGridView1.Columns[3].HeaderText = "Date";
dataGridView1.Columns[4].HeaderText = "Void Location";
dataGridView1.Columns[5].HeaderText = "Void Length";
dataGridView1.Columns[6].HeaderText = "Employee ID";
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
}
And this is my class
public OleDbDataReader GetVoidDGV(string VoidDate)
{
var conn = new OleDbConnection(oracleConnectionString);
conn.Open();
string query = "SELECT HEAT_RUN_NO, LOT_NO, SERIAL_NO, TO_CHAR(DATE_TIME, 'DD-MON-YYYY') as DATE_NO_TIME, VOID_LOC, cast(VOID_LENGTH as int) as VOID_LENGTH, EMPL_ID ";
query += "FROM MPCS.BRAZE_VOIDS ";
query += "WHERE TRUNC(DATE_TIME) = TO_DATE(?, 'dd-MON-yy')";
var cmd = new OleDbCommand(query, conn);
cmd.Parameters.AddWithValue("DATE_TIME", VoidDate);
rsMPCS = cmd.ExecuteReader();
rsMPCS.Read();
return rsMPCS;
}
Their should be 4 results. DGV only shows 3. Listview shows the 4.
This is just a screenshot of the 4 in Oracle SQL Developer. I've highlighted the one that isn't displayed. Line 1.
You're missing the first line because you are making a call to rsMPCS.Read(); before returning the reader, which advances the "record pointer", so only the subsequent records are loaded.
Remove that line and it will work.
EDIT: I am not able to format my code below, if any one can fix it.
I am new to sql queries and still learning.
Table Name: CommissionSetupTable.
I want to display #Paisa if gross_amount is between the range of #FromRate and #ToRate
Below is my code:
string paisa;
private void load_commission_setup()
{
SqlCeConnection conn = null;
SqlCeCommand cmd = null;
SqlCeDataReader rdr = null;
try
{
conn =
new SqlCeConnection(
#"Data Source=|DataDirectory|\Database.sdf;Persist Security Info=False");
conn.Open();
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
gross_amount = double.Parse(purchaseBillTableDataGridView[10, rowindex].Value.ToString());
// Gross Amount is between the ranges of FromRate and ToRate.
cmd = new SqlCeCommand("SELECT Paisa FROM CommissionSetupTable WHERE='" + gross_amount.ToString() + "' BETWEEN #FromRate AND #ToRate;", conn);
rdr = cmd.ExecuteReader();
if (rdr == null)
{
}
else
{
while (rdr.Read())
{
paisa = rdr["Paisa"].ToString();
}
rdr.Close();
cmd.Dispose();
}
}
finally
{
conn.Close();
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
purchaseBillTableDataGridView[11, rowindex].Value = paisa;
}
}
The correct syntax to use here is the following
cmd = new SqlCeCommand(#"SELECT Paisa FROM CommissionSetupTable
WHERE #gross BETWEEN FromRate AND ToRate;", conn);
Notice that the two field names should not be prefixed with #, otherwise they will be considered parameters placeholders.
And now, before executing the command, add the parameter for the #gross placeholder
cmd.Parameters.Add("#gross", SqlDbType.Decimal).Value = gross_amount;
I don't know what is the exact datatype of the columns FromRate and EndRate, but
note that you should use the correct datatype for your parameter. Do not pass a string and expect the database engine do the conversion for you. (or worse concatenate your value to the rest of the sql using ToString()). This is always wrong also if sometime the database engine could understand your values.
EDIT
Also, following your comments below, it appears that this line is wrong
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
If your DataGridView has the property AllowUserToAddRow set to True then you want to use
int rowindex = purchaseBillTableDataGridView.Rows.Count - 2;
because the first line points to the empty row added to the DataGridView for inserting a new record.
ComboBox doesn't show the data, I populate my combobox with data from my database this way:
private void PartDefective(string id)
{
cmd = new SQLiteCommand("Select * FROM Part_defective where testers = '" + id + "'", DBcon);
if (DBcon.State == ConnectionState.Closed)
DBcon.Open();
myDA = new SQLiteDataAdapter(cmd);
myDataSet = new DataSet();
myDA.Fill(myDataSet, "comboBox6");
this.comboBox6.DataSource = myDataSet.Tables["comboBox6"].DefaultView;
this.comboBox6.ValueMember = "Part";
this.comboBox6.DisplayMember = "Part";
this.comboBox6.SelectedItem = "ID";
this.comboBox6.SelectedIndex = -1;
DBcon.Close();
}
And to show the data from the database I used :
private void comboBox6_SelectedIndexChanged(object sender, EventArgs e)
{
if (this.comboBox6.SelectedValue == null)
{
testerid = "1";
}
else
{
part = this.comboBox6.SelectedText.ToString();
}
}
There is absolutely no reason to define the SelectedItem or SelectedIndex.
The SelectedIndexChanged Event is also completely redundant for displaying your combobox.
Remove these lines and see if it solved your problem.
this.comboBox6.SelectedItem = "ID";
this.comboBox6.SelectedIndex = -1;
If the combobox is still empty, the root of problem has to be with the fetching of your data and filling the datasource.
Put a breakpoint on this line:
this.comboBox6.DataSource = myDataSet.Tables["comboBox6"].DefaultView;
And then look at the value of myDataSet.Tables["comboBox6"] in the watch or quickwatch window. Are there any rows?
Also change your code:
string sql = "Select * FROM Part_defective where testers = '" + id + "'";
cmd = new SQLiteCommand(sql, DBcon);
Put a breakpoint there, see what the value of sql is.
Manually run the sql against your database and see if there are any results.