I was trying to add a combo box which could get all the product name but unfortunately I follow some tutorials and end up like this.
void fillCombo()
{
try
{
con.Open();
OleDbCommand command = new OleDbCommand("Select * from IblInventory");
command.Connection = con;
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
String product = reader.GetString("ProductName"); // << invalid argument
cmbProduct.Items.Add(product);
}
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
What could possibly the reason?
From the documentation of OleDbDataReader.GetString you will notice that the argument required by the method is an integer representing the position of the column in the returned record not its name.
If you (rightly) prefer to use the column name then you need to take a detour and use the GetOrdinal method to retrieve the position of the column given the name.
while (reader.Read())
{
int pos = reader.GetOrdinal("ProductName");
String product = reader.GetString(pos);
cmbProduct.Items.Add(product);
}
Another example, practically identical to your situation, can be found in the documentation page on MSDN about OleDbDataReader.GetOrdinal
It is also a common practice to write an extension method that allows you to write code as yours hiding the details of the mapping between name and position. You just need a static class with
public static class ReaderExtensions
{
public string GetString(this OleDbDataReader reader, string colName)
{
string result = "";
if(!string.IsNullOrEmpty(colName))
{
int pos = reader.GetOrdinal(colName);
result = reader.GetString(pos);
}
return result;
}
... other extensions for Int, Decimals, DateTime etc...
}
Now with this class in place and accessible you can call
string product = reader.GetString("ProductName");
it is working in my project
First fill your data in to datatable see the below code
DataTable results = new DataTable();
using(OleDbConnection conn = new OleDbConnection(connString))
{
OleDbCommand cmd = new OleDbCommand("Select * from IblInventory", conn);
conn.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);
adapter.Fill(results);
}
Now
cmbProduct.DataSource = results ;
cmbProduct.DisplayMember = "ProductName";
cmbProduct.ValueMember = "Id feild of IblInventory table";
Related
This is the code i am using to select Maximum RollNo based on Class field value.
But when there is no data about Class Field in Table. Then Error is generated.
using (var conn = new OleDbConnection(DatabaseObjects.ConnectionString))
{
conn.Open();
command = new OleDbCommand("select max(RollNo) as Roll from Students where Class = '"+cmbClass.Text+"'", conn);
OleDbDataReader dr = command.ExecuteReader();
if (!dr.IsDBNull(0))
{
while (dr.Read())
{
i = Convert.ToInt32(dr["Roll"]);
}
}
InvalidOperation Exception is occurring. I want to get value of RollNo if data is available in Table. If data is not available in Table then what should I do?
you are inversing the steps :
open the connection;
check is there is comming data;
check if the value is not null;
read the data;
try this :
while (dr.Read())
{
if (!dr.IsDBNull(0))
{
i = Convert.ToInt32(dr["Roll"]);
}
}
while your are attending just single value, use executeScalar to get the value ;
conn.Open();
command = new OleDbCommand("select isnull(max(RollNo),-1) as Roll from Students where Class = '"+cmbClass.Text+"'", conn);
int rollNo = (int) command.ExecuteScallar();
if(rollno !=-1)
{
// TODO :
}
My query returns results, but for some reason my DataTable always shows 0. The only thing I altered was the fact that I added parameters to the C# syntax (altho if I manually run the stored procedure it returns results). This is my syntax, does anyone see something that is incorrect syntactically in it?
protected void btnPress1464()
{
RunSQLStoredProc();
DataTable tableA = ebdb.Tables[0];
if (this.dtgAttendanceTracker.Items.Count == 0)
{
this.gvwTest.DataSource = tableA
this.gvwTest.DataBind();
}
}
public DataSet RunSQLStoredProc()
{
ebdb = new DataSet();
SqlQueryBuilder = new StringBuilder();
SqlQueryBuilder.Append("exec alphadawg ");
ebdb = DoThis(SqlQueryBuilder.ToString());
return ebdb;
}
public DataSet DoThis(string sqlQuery, int employeeid, DateTime hiredate, DateTime terminationdate)
{
try
{
System.Configuration.ConnectionStringSettings connstring = System.Configuration.ConfigurationManager.ConnectionStrings["SQLServer1"];
using (SqlConnection conn = new SqlConnection(connstring.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = sqlQuery;
cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#employeeid", employeeid.ToString());
cmd.Parameters.AddWithValue("#hiredate", hiredate.ToShortDateString());
cmd.Parameters.AddWithValue("#terminationdate", terminationdate.ToShortDateString());
conn.Open();
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
adapter.Fill(ebdb);
conn.Close();
}
}
return ebdb;
}
catch (Exception exception) { throw exception; }
}
The CommandText should only contain the stored-procedure name and not also exec if the command's CommandType is StoredProcedure. The StringBuilder is also redundant.
I also think that the way how you use AddWithValue with the wrong types could cause this issue(look at the last paragraph of my answer):
So not
SqlQueryBuilder = new StringBuilder();
SqlQueryBuilder.Append("exec alphadawg ");
ebdb = DoThis(SqlQueryBuilder.ToString());
but
ebdb = DoThis("alphadawg", otherParamaters...);
It's also bad practice to pass a sql-string to a method that executes it, that often introduces sql injection issues. You should not have a method DoThis but GetAlphaDawg which encapsulates the sql-query and only pass the parameter-values.
Apart from that, why do you return the DataSet from a method if it's actually a field in your class that you return? Instead initialize and fill it in the method, that's much clearer and also prevents issues when you load an already filled dataset(data will be appended by default).
This would be a possible implementation. Note that you shouldn't use AddWithValue and don't use String for DateTime but always use the correct type, all the more if you use AddWithValue which needs to infer the type from the value:
public DataSet GetAlphaDawg(int employeeid, DateTime hiredate, DateTime terminationdate)
{
DataSet dsAlpha = new DataSet();
try
{
System.Configuration.ConnectionStringSettings connstring = System.Configuration.ConfigurationManager.ConnectionStrings["SQLServer1"];
using (var conn = new SqlConnection(connstring.ConnectionString))
{
using (var da = new SqlDataAdapter("alphadawg", conn))
{
da.SelectCommand.CommandType = CommandType.StoredProcedure;
var parameter = da.SelectCommand.Parameters;
parameter.Add("#employeeid", SqlDbType.Int).Value = employeeid;
parameter.Add("#hiredate", SqlDbType.Date).Value = hiredate;
parameter.Add("#terminationdate", SqlDbType.Date).Value = terminationdate;
da.Fill(dsAlpha); // Open/Close not needed with Fill
return dsAlpha;
}
}
} catch (Exception) { throw; }
}
Since you use ToShortDateString, if you actually want to remove the time portion of your DateTime use DateTime.Date, for example:
parameter.Add("#hiredate", SqlDbType.Date).Value = hiredate.Date;
I am trying to show number of rows from a grid view using a label. I used SQL Count statement but it doesn't work. The problem is I only get only number 1 shown in the label which is not matched with the number of rows I have in my table! I have posted similar question but unfortunately no body gave a clear answer!
My codes as:
Basket.ac
public int td()
{
int customers;
//I tried this select query but still gets number 1
//String sql = String.Format("SELECT COUNT(*) FROM dbo.Baskets");
string sql = string.Format("SELECT COUNT(*) FROM Baskets");
customers = Db.RunQuery(sql).Rows.Count;
//customers = Convert.ToInt32(Db.RunQuery(sql).Rows.Count);
return customers;
}
DataBaseConn.ac
public class DataBaseConn
{
SqlConnection conn;
SqlCommand cmd;
DataTable tbl;
private void Intialise(CommandType commandtype, string DataBase)
{
conn = new SqlConnection();
cmd = new SqlCommand();
//Requirements
conn.ConnectionString = ConfigurationManager.ConnectionStrings[1].ToString();
cmd.Connection = conn;
cmd.CommandType = commandtype;
cmd.CommandText = DataBase;
conn.Open();
}
public int RunProcedure(string Procedure, SortedList ParameterV)
{
Intialise(CommandType.StoredProcedure, Procedure);
for (int i = 0; i < ParameterV.Count; i++)
try
{
if (ParameterV.GetByIndex(i) != null)
cmd.Parameters.AddWithValue(ParameterV.GetKey(i).ToString(),
PrameterV.GetByIndex(i).ToString());
}
catch { ;}
return RunUpdate();
}
public int RunUpdate(string InsDelUpd)
{
Intialise(CommandType.Text, InsDelUpd);
return RunUpdate();
}
private int RunUpdate()
{
try
{
int x = cmd.ExecuteNonQuery();
conn.Close();
return x;
}
catch (SqlException ex)
{
conn.Close();
return ex.Number;
}
}
public DataTable RunQuery(string Select)
{
Intialise(CommandType.Text, Select);
tbl = new DataTable();
tbl.Load(cmd.ExecuteReader());
conn.Close();
return tbl;
}
public bool EData(string selection)
{
if (RunQuery(selection).Rows.Count > 0)
return true;
else
return false;
}
}
Basket.aspx
lblQueue.Text = _b.td().ToString();
You don't want to return the data table's .Rows.Count - this will always be 1 (as in 1 row(s) affected) for your count(*) query.
You should instead look at using ExecuteScalar to return the first column of the first row from your query
I'm not sure how you want to build this into your DataBaseConn data helper class, but the gist of it is you need the following sequence:
using (var conn = new SqlConnection(connectionStringHere))
using (var cmd = new SqlCommand(conn))
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT COUNT(*) FROM Baskets";
return (int)cmd.ExecuteScalar();
}
Edit
If you aren't able to extend your DataBaseConn helper with an ExecuteScalar, then I guess you'll be able to use the existing RunQuery method which returns a DataTable. Just scrape the first column of the first row like so:
return Db.RunQuery(sql).Rows[0].Field<int>(0);
As a side note, you might look at replacing your DataHelper entirely with the Microsoft Patterns and Practices Data Application Access Block (DAAB), or, if you prefer, look at using an ORM like Entity Framework. By upgrading to a mainstream Data Access encapsulation, you won't need to spend as much time debugging data access issues like this one :)
I'm using c# in a ASP.Net web application.I have the following query:
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["chestionar"].ConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("select * from personal,Intrebari where personal.cod_numeric_personal=#cnp AND Intrebari.id_intrebare=14 AND Intrebari.id_intrebare=15 ", con);
cmd.Parameters.AddWithValue("#cnp", Session["sesiune_cnp"]);
SqlDataReader rdr;
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
lbl1.Text = rdr["Nume"].ToString();
intrebare6.Text = rdr["Intrebari"].ToString();
intrebare7.Text = rdr["Intrebari"].ToString();
}
I want those two values for id_intrebare=14 and 15 to assign it to those 2 labels.How can i refer to those?
In order to read stuff from the reader you need to include it in the select statement for you sql, it is better to select it explicitly rather than use select *.
but you are not currently going to get any results returned because id_intrebare cannot be both 14 and 15
you then need to read id_intreabare ratherr than Intreabari.
Try this, notice the try catch block, I also changed your SQL query.
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["chestionar"].ConnectionString);
string qry="select * from personal,Intrebari where personal.cod_numeric_personal=#cnp AND Intrebari.id_intrebare IN (14,15);
SqlCommand cmd = new SqlCommand(qry, con);
cmd.Parameters.AddWithValue("#cnp", Session["sesiune_cnp"]);
try
{
con.Open();
SqlDataReader rdr= cmd.ExecuteReader();
if(rdr.HasRows)
{
while (rdr.Read())
{
lbl1.Text = rdr["Nume"].ToString();
intrebare6.Text = rdr["Intrebari"].ToString();
intrebare7.Text = rdr["Intrebari"].ToString();
}
}
}
catch(SQLException ex)
{
lblStatus.Text="An error occured"+ex.Message;
throw ex;
}
finally
{
con.Close();
con.Dispose();
}
If you want to assign texts to different numbered lables in a loop, you can refer to the control id with FindControl of the current page
int numeOrdinal = reader.GetOrdinal("Nume");
int intrebariOrdinal = reader.GetOrdinal("Intrebari");
int i = 1;
while (rdr.Read()) {
// Nume (Romanian) = Name
page.FindControl("lbl" + i).Text = reader.IsDBNull(numeOrdinal)
? ""
: rdr.GetString(numeOrdinal);
// Intrebari (Romanian) = Question
page.FindControl("intrebari" + i + 5).Text = reader.IsDBNull(intrebariOrdinal)
? ""
: rdr.GetString(intrebariOrdinal);
i++;
}
Try using cmd.ExecuteScalar it will return the first reuslt it finds so you have to define your conditions well. Also it returns object type so you will have to cast the result
I'm not really used to C# sharp but have used VB.NET before.
I'm needing to set the value of text fields, dropdowns etc from data from a query. To enter the data I have been using a class Computer with the method saveComputer() that takes values from user controls. Now I want an edit page that uses the id from url & uses getComputer(id) from Computer class and returns the values to be set to the user controls. I'm unsure about using this method to set the control values.
Edit.aspx.cs
protected void btnSave_Click(object sender, EventArgs e)
{
int id = 3; //will be replaced to GET value
Computer comp = new Computer();
//comp.updateComputer(ref id);
}
My Computer class
public getComputer(ref int id)
{
DataSet data = new DataSet();
using (SqlConnection conn = new SqlConnection(
"Server=JURA;Database=ReadyForSeven;User id=;Password="))
{
String sql = "SELECT * FROM computers WHERE id=#id";
//replace contatenation of variable with parameter name
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = sql.ToString();
cmd.CommandType = CommandType.Text;
//Define SqlParameter object and assign value to the parameter
cmd.Parameters.Add("#id", SqlDbType.Int);
cmd.Parameters["#id"].Value = id;
try
{
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(data);
// return data here
}
}
catch (SqlException ex)
{
//send user to error page and log message
}
}
}
So what I'm wanting to achieve is using the getcomputer method of Computer to set the values of the controls on Edit.aspx
Can anyone help me out?
You'll need to modify your getComputer method to return a DataSet like:
public DataSet getComputer(int id) {
Once that's done we can call it and populate the form controls on the page load with something like:
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
int id = 3; // get from querystring
DataSet ds = getComputer(id);
DataRow dr = ds.Tables[0].Rows[0]; // get the first row returned
// populate form controls
txtFirstName.Text = dr["FirstName"].ToString();
ddlState.SelectedValue = dr["State"].ToString();
}
}
Below is an updated version of getComputer that will always return a value and is a little tighter:
public DataSet getComputer(int id) // you don't need to pass int by ref unless you're planning on changing it inside this method
{
DataSet data = new DataSet();
using (SqlConnection conn = new SqlConnection("Server=JURA;Database=ReadyForSeven;User id=;Password=")) {
using (SqlCommand cmd = new SqlCommand("SELECT * FROM computers WHERE id = #id", conn)) {
cmd.Parameters.AddWithValue("id", id);
using (SqlDataAdapter da = new SqlDataAdapter(cmd)) {
da.Fill(data);
return data;
}
}
}
}
I had to remove the try/catch blog to ensure the method always returned a value. If you absolutely need the try/catch block you'll need to return an empty DataSet at the end of the method to get to compile correctly.