Cannot retrieve data from database in C# - c#

I have an application,which is not able to fetch data from the database for this specific form, while other forms are working fine.
I am using this form to fetch data from database and then display that data onto labels on an another form.
The code for fetching data is:
string PName, DName, Psex, PPhoneNo, PAddress, Treatment, Teethno, PAge, Amount;
SqlDataAdapter a = new SqlDataAdapter("Select bills.BillNo,bills.PName,bills.DName,bills.PAge,bills.PSex,bills.PPhoneNo,bills.PAddress,bills.Treatment,bills.Amount,bills.Teethno,addpro.Medicines from bills,addpro where bills.BillNo=" + bno, Program.con);
DataTable t = new DataTable();
a.Fill(t);
PAge = Convert.ToString(t.Rows[3]);
Amount = Convert.ToString(t.Rows[8]);
PName = Convert.ToString(t.Rows[1]);
DName = Convert.ToString(t.Rows[2]);
Psex = Convert.ToString(t.Rows[4]);
PPhoneNo = Convert.ToString(t.Rows[5]);
PAddress = Convert.ToString(t.Rows[6]);
Treatment = Convert.ToString(t.Rows[7]);
Teethno = Convert.ToString(t.Rows[9]);
frmPrint sa=new frmPrint();
sa.start(bno, PAge, Amount, PName, DName, Psex, PPhoneNo, PAddress, Treatment, Teethno);
when i try to load the next form which displays the data from this DataTable on labels it gives the following error:-
There is no row at position 3.

Your're using Row and you want to be using Column:
foreach(DataRow row in t.Rows)
{
PAge = row["PAge"].ToString();
Amount = row["Amount"].ToString();
PName = row["PName"].ToString();
DName = row["DName"].ToString();
Psex = row["PSex"].ToString();
PPhoneNo = row["PPhoneNo"].ToString();
PAddress = row["PAddress"].ToString();
Treatment = row["Treatment"].ToString();
Teethno = row["Teethno"].ToString();
}
Instead of using the number to identify the column, use the name. If the order of the query was to change for any reason, this would not have an impact on your code. If you used the Ordinal number, then you would need to change your row[n] code too since the order would have changed.

You are accessing different rows for each field.
You should access the first row and then different columns:
t.Rows[0].Columns[0]
t.Rows[0].Columns[1]
t.Rows[0].Columns[2]
t.Rows[0].Columns[3]
...

Seems like you need to use [Columns]
DataTable t = new DataTable();
a.Fill(t);
PAge = Convert.ToString(t.Rows[0]["ColumnsName"]);
// and so on

Related

How to handle zero rows returned when binding data to DataGridView

I'm populating a DGV with data from a database and everything works fine, with the exception of when 0 rows are returned to the DataTable that populates the DGV. And I'm not sure how exactly to handle that situation, which I do need to allow for due to the program requirements.
Here's the Form code that calls the data binding method:
public void PopulateDgvCategories()
{
string companyFilter = cboSelectCompany.Text;
string categoryFilter = cboSelectCategory.Text;
db categoriesData = new db();
if (categoryFilter == "All Categories")
{
string catsQuery = "SELECT id, category, old_value, old_desc, new_value, new_desc, reference1, reference2 " +
"FROM masterfiles.xref WHERE company_name = #company ORDER BY category, old_value";
this.dtCategories = categoriesData.GetDgvData(catsQuery, companyFilter, categoryFilter);
}
else
{
string catsQuery = "SELECT id, category, old_value, old_desc, new_value, new_desc, reference1, reference2 " +
"FROM masterfiles.xref WHERE company_name = #company and category = #category ORDER BY old_value";
this.dtCategories = categoriesData.GetDgvData(catsQuery, companyFilter, categoryFilter);
}
// Need to check this.dtCategories.Rows.Count
// If 0, then need to figure out how to handle that
dgvCategories.DataSource = this.dtCategories;
dgvCategories.Columns[0].Visible = false;
dgvCategories.Rows[0].Cells[0].Selected = false;
}
And here's how I'm retrieving the data and filling the DataTable:
public DataTable GetDgvData(string selectQuery, string companyFilter, string categoryFilter)
{
using (NpgsqlConnection conn = new NpgsqlConnection(connString))
using (NpgsqlCommand cmd = new NpgsqlCommand(selectQuery, conn))
{
cmd.Parameters.Add(new NpgsqlParameter("company", companyFilter));
if (categoryFilter != "All Categories") cmd.Parameters.Add(new NpgsqlParameter("category", categoryFilter));
DataSet ds = new DataSet();
conn.Open();
using (NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd))
{
da.Fill(ds);
}
conn.Close();
return ds.Tables[0];
}
}
It is possible for the categoryFilter variable to cause the query to return 0 rows.
What is the best way to handle that? I'm thinking manually create the DGV with just the header row (column names) and display a MessageBox saying no rows were returned. Is that possible/feasible and would it be the best way to handle that?
There is absolutely no problem binding a datatable with zero rows - it will have a set of columns of the correct types regardless and will autocreate columns if the AutoGenerateColumns property is true
The problems come simply because you're trying to access a datagridview cell at 0,0 without making sure it exists, so you could put:
dgvCategories.DataSource = this.dtCategories;
dgvCategories.Columns[0].Visible = false;
it(dtCategories.Rows.Count > 0)
dgvCategories.Rows[0].Cells[0].Selected = false;
But you should just take this line out completely - it doesn't do anything anyway; it doesn't hide the blue selection highlight in the top left and a freshly bound datagridview's top left cell is already Selected=false so you're not achieving anything other than an exception with this line of code
If you want to hide the blue selection highlight when a DGV isn't focused, set the cell's Style.SelectionBackColor to be the same as its Style.BackColor, but do set it to something visible when the user focuses the grid or they will struggle to understand why they can't make that cell highlighted.
If you want to remove the ghost row that allows you to add new values, set AllowUserToAddRows to false
If you want to let the user know there were no rows from a recent search, place a label on top of the DGV with a "Your search 'whatever' returned no results" and set its visibility depending on whether there are rows:
lblNoResults.Text = $"Your search '{categoryFilter}' returned no rows";
lblNoResults.Visible = dtCategories.Rows.Count == 0;
Finally, you don't need to use a DataSet when all you want is a DataTable. A datadapter can fill a datatable; there is no need to go to the extra wasted effort of using a dataset - it's like using a List<string> and accessing it's 0th element when all you want is a string. You also don't need to open/close the connection - dataadapter knows how to do this itself. It is intelligent enough to not close a connection opened elsewhere (in case there is a transaction in progress):
DataTable dt = new DataTale();
using (NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd))
{
da.Fill(dt);
}
return dt;

Dropdown list to show all values

I have been working on asp.net. I have a registration form with grid view.
The grid view contains the id of dropdownlist(ddl).
when i select the grid view ,all values have to be shown in appropriate fields in registration form.
For ddl, from the ddl id value in grid view ,appropriate dropdown list text is shown in dropdownlist.
THE PROBLEM COMES HERE, dropdown list showing only the appropriate value and AGAIN IT CANNOT BE CLICKED AND POPULATED FOR UPDATE BUTTON
enter image description here.
cmd.CommandText = "SELECT * FROM COMPANY WHERE COMPANYID='" + dbCompany + "'";
txtTextBox1.Text = newcmpid;
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());
ddlCompanyName.DataSource = dt;
ddlCompanyName.DataTextField = "COMPANYNAME";
ddlCompanyName.DataValueField = "COMPANYID";
ddlCompanyName.DataBind();
HOW TO POPULATE THE DROPDOWNLIST WITH ALL ELEMENTS BY THE SAME TIME HIGHLIGHTING THE APPROPRIATE VALUE
To achive selection just use:
ddlCompanyName.Items.FindByValue(dbCompany).Selected = true;
But You should also notice that you SQL query is dangorous. It allows to create SQL inject attack. Instead of concatenating it you should SQL params.
So the full code could be like this:
cmd.CommandText = "SELECT * FROM COMPANY WHERE COMPANYID=#ID;";
cmd.Parameters.Add("#ID", SqlDbType.Int);
cmd.Parameters["#ID"].Value = dbCompany;
txtTextBox1.Text = newcmpid;
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());
ddlCompanyName.DataSource = dt;
ddlCompanyName.DataTextField = "COMPANYNAME";
ddlCompanyName.DataValueField = "COMPANYID";
ddlCompanyName.DataBind();
ddlCompanyName.Items.FindByValue(dbCompany).Selected = true;

Add summary to a datagridview in windows Form Application

I want to add a row in datagridview under my last row which shows summary of the records.So I Fill my dataset and then add a row in it, afterwards I Bind it to a datagridview and then when I try to assign my new row with value it gives me error that cannot convert date time to string as The fourth column datatype is datetime.SO my question is can we change column type of a specific row cell ,If no then how can I achieve what I want to do?
string SelectGroupQuery = "Select * From GroupMembers Where GID=#Id ";
using (SqlConnection conGroup = new SqlConnection(ConnectionString.ToString()))
{
using (SqlCommand commandGroup = new SqlCommand(SelectGroupQuery, conGroup))
{
commandGroup.CommandType = CommandType.Text;
commandGroup.Parameters.Add(new SqlParameter("Id", Id));
SqlDataAdapter da = new SqlDataAdapter(commandGroup);
DataSet ds = new DataSet();
da.Fill(ds);
d1 = new DataGridView();
this.Controls.Add(d1);
d1.Location = new Point(50,y);
d1.Size = new Size(600, 300);
dr = ds.Tables[0].NewRow();
ds.Tables[0].Rows.Add(dr);
d1.DataSource = ds.Tables[0];
d1.Columns[4].ValueType = typeof(string);
d1.Rows[d1.Rows.Count-2].Cells[4].Value = "Total Amount";
y = y + 400;
}
}
Changing the type of a particular cell could be done for some of the column types. See this answer. But I wouldn't recommend it.
It is tricky to use a row in datagridview for displaying summary as it brings in some problems (more when bound to database). You could create your summary row using textboxes outside the datagridview and add the summary data to them. Check this codeproject link for working example.
Instead of assigning the value to the cell, you could fake it by handling the CellFormatting event. If e.ColumnIndex = 4 and e.RowIndex is the last row in the grid, set the formatted value to the label you want and set the property of the EventArgs to tell it you formatted the value.
If you aren't making the whole DataGridView read-only, you probably want to also handle the CellBeginEdit event and cancel the edit if it's the summary row.

Any data table query builder available, like sql query builder?

I am new in net I want to use data table instead of a database.
I want to know that why is data table query different from an sql query?
I want to find a value from data table:
SELECT dbo.General_Ledger.Entry_Amount FROM dbo.General_Ledger WHERE Account_number=lbDebit_Account_numer
and
using (SqlConnection connect = new SqlConnection(con))
{
int index = lbDebit_Account.FindString(txtDebit_Account.Text);
if (0 <= index)
{
lbDebit_Account.SelectedIndex = index;
}
SqlDataAdapter da3 = new SqlDataAdapter("SELECT *FROM dbo.General_Ledger", connect);
DataTable dt1 = new DataTable();
da3.Fill(dt1);
string lbDebit_Account_numer = lbDebit_Account.SelectedValue.ToString();
string row;
row= Convert.ToString(dt1.Select(string.Format("'Account_number'={0}",lbDebit_Account_numer)));
}
I want to perform this query:
SELECT dbo.General_Ledger.Entry_Amount FROM dbo.General_Ledger WHERE Account_number=lbDebit_Account_numer
So you'll want to parameterize your query:
SqlDataAdapter da3 = new SqlDataAdapter("SELECT * FROM dbo.General_Ledger WHERE Account_number = #Account_number");
da3.SelectCommand.Parameters.AddWithValue("#Account_number", lbDebit_Account.SelectedValue);
DataTable dt1 = new DataTable();
da3.Fill(dt1);
and now you'll have just the one row you want and you can recover it like this:
DataRow dr = dt1.Rows[0];
and then you can grab values off of that row a number of different ways:
var val = dr[0]; // grabs the value of the first column in the result list
var val = dr["fieldname"] // grabs the value of a specific field name
and there are even some methods that will returned typed data because the aforementioned return an object since the underlying value could be a number of things. So, if it were a string field you were after you could do something like:
var val = dr.Field<string>(0) // grabs the value of the first column and returns it typed as a string
var val = dr.Field<string>("fieldname") // grabs a field and returns it typed as a string
It very simple, u want to filter the DataTable[dt1] base on this string[lbDebit_Account_numer]
DataRow dr = dt1.Select("Account_number = '"+lbDebit_Account_numer ="'");
u can use
AND OR
operators
single code['] need for string variables to compare.
here u get data-row, all cell will in an array format you select any cell.
You can try to use DefaultView.RowFilter property of DataTable class.
Example:
dataTable.DefaultView.RowFilter = "Account_number=1";

OleDB Data not reading from the correct row

I have the following method created and previously stock1Label to stock3Label were able to output the correct values from the database however after i added more rows to my ProductsTable, source.Rows[0][0], [1][0], etc. seems to be taking values from row 8 onwards of my table instead of row 1, anyone know why this is happening?
private void UpdateStocks()
{
string query = "SELECT pQty FROM ProductsTable";
OleDbDataAdapter dAdapter = new OleDbDataAdapter(query, DBconn);
DataTable source = new DataTable();
dAdapter.Fill(source);
stock1Label.Text = source.Rows[0][0].ToString();
stock2Label.Text = source.Rows[1][0].ToString();
stock3Label.Text = source.Rows[2][0].ToString();
stock4Label.Text = source.Rows[3][0].ToString();
stock5Label.Text = source.Rows[4][0].ToString();
stock6Label.Text = source.Rows[5][0].ToString();
}
Most (all?) database systems do not have defined orders.
You will receive rows in non-determinstic storage order, not in the order you inserted them.
To receive a meaningful consistent ordering, you need to add an ORDER BY clause.

Categories

Resources