I'm relatively new but I've been researching this issue for over 2 days, so I think I've done my due diligence ... however if this has already been answered before I apologize.
My basic issue is I'm trying to create some dependent combo boxes. The wrinkle is the displayed value is typically not the lookup value for the next query/Combo box (I'm using an OLEDB compliant data base)
For example: Table1 (T1) contains ID (int) & NM (string), Table2 (T2) contains ID (int) & STATUS (string). I run Query1 (Q1) to display T1.NM in Combobox1 (CB1), when selected I run Query1a to lookup/get the selected Table1.ID to pass to Query2 that populates Combobox2. The connection string and Q1 work fine, CB1 displays properly, but once I select this error is thrown:
"OleDbException .. SQL Passthru expression ... using equals (=) has components that are of different data types"
// ** Initial connection & populate CB1 - This works fine **
public void comboboxLoad()
{
string conn3str = <Connection String >;
string query1 = "select NM from Table1 where REFVALUE=1 ; ";
OleDbConnection conn3 = new OleDbConnection(conn3str);
OleDbCommand tblRow1 = new OleDbCommand(query1, conn3);
OleDbDataReader rdRow1;
try
{
conn3.Open();
lblConnState.Text = "Connection Successful";
rdRow1 = tblRow1.ExecuteReader();
while (rdRow1.Read())
{
int colindx1 = rdRow1.GetOrdinal("NM");
string sItbl = rdRow1.GetString(colindx1);
CB1.Items.Add(sItbl);
}
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
}
}
// ** Get value from CB1, create query to populate CB2 **
private void CB1_SelectedIndexChanged(object sender, EventArgs e)
{
string conn3str = <Connection String >;
OleDbConnection conn3 = new OleDbConnection(conn3str);
conn3.Open();
// Pass the selected value from CB1 (string) equal to Table1.NM (string)
string query1a = "select ID from Table1 where NM = '" + CB1.Text + "' ; ";
OleDbCommand TabID = new OleDbCommand(query1a, conn3);
int TabId2 = Convert.ToInt32(TabID.ExecuteScalar());
// Pass the variable TabId2 (int) equal to Table2.ID (int)
string query2 = "select STATUS from Table2 where ID = '" + TabId2 + "'; ";
OleDbCommand tblRow2 = new OleDbCommand(query2, conn3);
// OleDbDataReader rdTabID;
// OleDbDataReader rdRow2;
try
{
OleDbDataReader rdRow2 = TabID.ExecuteReader();
OleDbDataReader rdTabID = tblRow2.ExecuteReader(); // ** Error points to this line **
while (rdRow2.Read())
{
int TabIdidx = rdTabID.GetOrdinal("ID");
string TabIDVal = rdTabID.GetString(TabIdidx);
// Pass reference ID to label on form
lblBTableID.Text = TabId2.ToString();
int colindx1 = rdRow2.GetOrdinal("STATUS");
string sIntVal = rdRow2.GetString(colindx1);
cmbLowLvl.Items.Add(sIntVal);
}
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
}
}
Are you positive you're getting a value back on this line int TabId2 = Convert.ToInt32(TabID.ExecuteScalar());?
Convert.ToInt32 doesn't throw a ArgumentNullException like int.Parse does so it's possible that the variable is not getting set.
Also you may want to consider changing your queries to use parameterized SQL rather than concatenation for security purposes.
https://msdn.microsoft.com/en-us/library/system.data.oledb.oledbcommand.parameters(v=vs.110).aspx
I've been able to figure out the problem. I'm really not sure why it didn't work originally, but I think it was a reader mismatch, since I was only looking for a single value back from the query ExecuteScalar() seemed to do the trick and I didn't need the 'while' loop. The working code is below.
Next I'll need to pass this return value (ID) in my next query to populate CB2. Thanks #
private void CB1_SelectedIndexChanged(object sender, EventArgs e)
{
string conn3str = <Connection String >;
OleDbConnection conn3 = new OleDbConnection(conn3str);
// Pass the selected value from CB1 (string) equal to Table1.NM (string) but return the int ID.
OleDbCommand tblRow2 = new OleDbCommand("select ID from Table1 where NM= '"+ CB1.Text +"' ;" , conn3);
try
{
conn3.Open();
string r2 = Convert.ToString(tblRow2.ExecuteScalar());
MessageBox.Show(r2);
lblBTableID.Text = "ID Code= " + r2;
conn3.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
}
}
Related
I want to pass an user input to a where clause in a method.
The method has sql query and it uses parameter, but it seems like the parameter is not passed to the query. (I debugged and saw it does not go into the while loop.
My code is below:
Console.WriteLine("Enter your name: ");
string name = Console.ReadLine();
string prm = "\"" + name + "\""; // Doublequote a string
//execute method
CheckCustomer(prm);
private static string CheckCustomer(string cusName)
{
string cust = "null";
try
{
Console.WriteLine("\nChecking custoemr...\n");
// Sql Select Query
string sql = "SELECT * FROM Customer WHERE CustomerName = #CusName";
SqlCommand cmd = new SqlCommand(sql, sqlConnection);
cmd.Parameters.AddWithValue("#CusName", cusName);
SqlDataReader dr;
dr = cmd.ExecuteReader();
string strCusname = "Customer Name Found";
Console.WriteLine("{0}", strCusname.PadRight(25));
Console.WriteLine("==============================");
while (dr.Read())
{
////reading from the datareader
cust = dr["CustomerName"].ToString();
}
dr.Close();
return cust;
}
catch (SqlException ex)
{
// Display error
Console.WriteLine("Error: " + ex.ToString());
return null;
}
}
When I execute CheckCustomer() without the where clause, it works perfect.
However, once I add a parameter, does not go inside while loop; it goes to dr.Close(); directly.
What is wrong with this code?
To check for nulls in SQL server you use "is null" instead of "where field = null"
if you tried the query in sql server management studio u will not get any result
since string cust = "null"; that means ur code checks for customerName = null, but as i stated that this is not the right way to check for null and this query will not return any result, and since there is no result that means dr.Read() will evaluate to false and the while loop won't be executed
You don't need to wrap the string value in quote. You can remove this line, since SqlParameter will handle that for you.
string prm = "\"" + name + "\""; // Doublequote a string
Also, if you want your query to support optional null values (i.e. where NULL implies that you DO NOT want to filter on customer name then you can simpy do:
SELECT * FROM Customer WHERE CustomerName = ISNULL(#CusName, CustomerName)
In your parameter section you can do something like:
cmd.Parameters.AddWithValue("#CusName", string.IsNullOrWhiteSpace(cusName) ? DbNull.Value: cusName);
If you don't want to allow nulls then you can leave the SQL query as-is as a throw a new ArgumentNullException at the top of your query method (i.e. add a guard clause):
if (string.IsNullOrWhiteSpace(CustomerName)) throw new ArgumentNullException(nameof(CustomerName));
Your query appears to be searching for the first customer with matching name. In that case you should probably add a "TOP 1" to avoid needless overhead:
SELECT TOP 1 * FROM Customer WHERE CustomerName = ISNULL(#CusName, CustomerName)
Console.WriteLine("Enter your name: ");
string name = Console.ReadLine();
string prm = "\"" + name + "\""; // Doublequote a string
//execute method
CheckCustomer(prm);
private static string CheckCustomer(string cusName)
{
string cust = "null";
try
{
Console.WriteLine("\nChecking custoemr...\n");
// Sql Select Query
string sql = "SELECT * FROM Customer WHERE CustomerName = #CusName";
SqlCommand cmd = new SqlCommand(sql, sqlConnection);
cmd.Parameters.AddWithValue("#CusName", cusName);
SqlDataReader dr;
dr = cmd.ExecuteReader();
string strCusname = "Customer Name Found";
Console.WriteLine("{0}", strCusname.PadRight(25));
Console.WriteLine("==============================");
while (dr.Read())
{
////reading from the datareader
cust = dr["CustomerName"].ToString();
}
dr.Close();
return cust;
}
catch (SqlException ex)
{
// Display error
Console.WriteLine("Error: " + ex.ToString());
return null;
}
}
try this.
I created a C# application to query and insert a product database. However I am here with a small doubt and if anyone can help me i thank you right away.
The following is:
I have a form to insert data into the database created in MS Access 2007, with the values of reference, sale number, client code, client name, quantity and position number in archive;
Here is my code until the moment:
private void btn_save_Click(object sender, EventArgs e)
{
OleDbConnection con = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=product.accdb");
OleDbCommand check_sn = new OleDbCommand("SELECT COUNT(*) FROM [product] WHERE ([sn] = #sn)", con);
OleDbCommand check_reference = new OleDbCommand("SELECT COUNT(*) FROM [product] WHERE ([reference] = #ref)", con);
OleDbCommand check_number = new OleDbCommand("SELECT COUNT(*) FROM [product] WHERE ([number] = #num)", con);
con.Open();
check_reference.Parameters.AddWithValue("#ref", textBox_ref.Text);
check_sn.Parameters.AddWithValue("#sn", textBox_sn.Text);
check_number.Parameters.AddWithValue("#num", textBox_num.Text);
int refExist = (int)check_reference.ExecuteScalar();
int SNExist = (int)check_sn.ExecuteScalar();
int numExist = (int)check_number.ExecuteScalar();
if (refExist > 0)
{
MessageBox.Show("A product with this reference already exists....!");
}
else if (SNExist> 0)
{
MessageBox.Show("A product with this sale number already exists....!");
}
else if (numExist > 0)
{
MessageBox.Show("A product with this archive number already exists....!");
}
else
{
try
{
String reference = textBox_ref.Text.ToString();
String sn = textBox_ov.Text.ToString();
String cod_client = textBox_cod.Text.ToString();
String client = textBox_cliente.Text.ToString();
String qtd = textBox_qtd.Text.ToString();
String number = textBox_num.Text.ToString(); //This will be the incremented number
String my_query = "INSERT INTO product(reference,sn,cod_client,client,qtd,number)VALUES('" + reference + "','" + sn + "','" + cod_client + "','" + client + "','" + qtd + "','" + number + "')";
OleDbCommand cmd = new OleDbCommand(my_query, con);
cmd.ExecuteNonQuery();
MessageBox.Show("Data saved successfully...!");
}
catch (Exception ex)
{
MessageBox.Show("Failed due to" + ex.Message);
}
finally
{
con.Close();
}
cleanTextBoxes(this.Controls);
}
}
private void search_btn_Click(object sender, EventArgs e)
{
Form search = new Form_search();
search.Show();
this.Hide();
}
}
}
How can i make it so that instead of manually entering the position number in archive in the textbox it can be automatically filled with the new position in archive. For example, my last product inserted has the position 50 in archive, the new one will automatically be number 51 and so on ... and this number should appear automatically in the textbox so that the user knows what is the number of the new registered product.
Thank you,
Ok i have tried this and works but how i do now to increment this value +1?
OleDbConnection con = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Aneis_Calibre.accdb");
con.Open();
OleDbDataReader myReader = null;
OleDbCommand number = new OleDbCommand("SELECT TOP 1 [number] FROM product Order by [number] desc", con);
myReader = number.ExecuteReader();
while (myReader.Read())
{
textBox_num.Text = (myReader["number"].ToString());
}
con.Close();
Inside your query, you would want to do something along these lines.
INSERT ...
OUTPUT inserted.identity_column
VALUES (...)
That will return a row with a value for the id. The identity column in SQL will always increment automatically for you. Which would alleviate your approach where you grab the last record and do:
int.TryParse(reader["..."]?.ToString(), out int id);
textbox.Text = id++;
By using the scalar, or reader though I would recommend scalar if you return a single column with a modified SQL query would result in the exact newly inserted id.
Is there anything wrong with my code? It is not showing data in textboxes. The same funtion is working for another table in database but not for this one.
private void metroButton1_Click(object sender, EventArgs e)
{
con = new SqlConnection(constr);
String query = "Select FROM Student WHERE Std_ID = '" + metroTextBox1.Text + "'";
cmd = new SqlCommand(query, con);
con.Open();
try
{
using (SqlDataReader read = cmd.ExecuteReader())
{
while (read.Read())
{
// metroTextBox1.Text = (read["ID"].ToString());
metroTextBox2.Text = (read["Name"].ToString());
metroTextBox3.Text = (read["F_Name"].ToString());
metroTextBox4.Text = (read["Std_Age"].ToString());
metroTextBox5.Text = (read["Address"].ToString());
metroTextBox6.Text = (read["Program"].ToString());
metroComboBox1.Text = (read["Course"].ToString());
}
}
}
finally
{
con.Close();
}
}
you need to give column names in the select statement or select *
for example :
String query = "Select * from Student WHERE Std_ID = '" + metroTextBox1.Text + "'";
Not related to Question: you can change the while loop to if condition if you have one record for given id. even there are many records for given id you will see the last record data only because of the while loop will overwrite the textboxes in every record.
Update :
There isn't anything wrong with Syntax because the same syntax is
working for modifying teacher funtion.
No, this is incorrect, remove the try catch in your code then you will see the exception of syntax error
I have a comboBox and a checkListBox in my windows form application that connected to my SQL database. I got the binding data part working, but I am not sure how to show the datas in checkListBox when the comboBox item is selected. Let say I have 10 items in my comboBox that bind with my SQL database and they are under the column name ("application name ") such as excel, word, android, eclipse etc.... I call this method when the form begin to load. Sorry for the long code.
Here is my code for that applicationComboBox
private void loadComboBox()
{
myConn = new SqlConnection("Server = localhost; Initial Catalog= dbName; Trusted_Connection = True");
try
{
myConn.Open();
//my table name is Application_Detail
string query = "select * from Application_Detail";
myCommand = new SqlCommand(query, myConn);
//reading the value from the query
SqlDataReader dr = myCommand.ExecuteReader();
//Reading all the value one by one
while (dr.Read())
{
//column is 1 in Application_Detail Data
//GetString(1) display the 2nd column of the table
string name = dr.GetString(1);
//display the application name in column 2 -
applicationComboBox.Items.Add(name);
}
myConn.Close();
}catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The outcome of this part of code is:
//label Name //Application Name
Application Name:
Excel
Word
NotePad
PowerPoint
SubLime
Eclipse
After I call this method, I want to display the teacher name that is according to what the user selected in this applicationComboBox. So if teacher 1,2,3 is using Excel and the user selected excel from the comboBox, the checkListBox will display teacher 1,2,3 and vice versa. To do this, I call the method at the comboBox1_SelectedIndexChanged method because I want to display the detail when I select an item from the comboBox. Below is my code
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
//I check if the comboBox index is at 0, it disable the button.
if (applicationComboBox.SelectedIndex == 0)
{
exportButton.Enabled = false;
this.teacherCheckListBox.DataSource = null;
teacherCheckListBox.Items.Clear();
}
//it it is not at 0,
else
{
exportButton.Enabled = true;
//call this method
fill_checkListBox();
}
//teacherCheckListBox
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void fill_checkListBox()
{
myConn = new SqlConnection("Server = localhost; Initial Catalog= dbName; Trusted_Connection = True");
try
{
myConn.Open();
//for reading purpose, I break down by long statement
//In this statement, I left join 3 table (Teacher_Detail, AppUser_Detail, and Application_Detail table). My AppUser_Detail contains all 3 id (teacherId, applicationId, and AppUserId). I then set filter the table using `where` keyWord to make the applicationId = the comboBox text
string query = "SELECT
td.chineseName,
ad.applicationId,
aud.applicationId,
ad.applicationName
FROM[AppUser_Detail] as aud
LEFT JOIN[Teacher_Detail] as td
ON aud.teacherId = td.teacherId
LEFT JOIN[Application_Detail] as ad
ON aud.applicationId = ad.applicationId
where aud.applicationId = '" + applicationComboBox.Text + "' AND NOT(td.teacherId IS NULL)
";
myCommand = new SqlCommand(query, myConn);
//reading the value from the query
SqlDataReader dr = myCommand.ExecuteReader();
//Reading all the value one by one
while (dr.Read())
{
//column is 0 where the teacherName belong in my Teacher_Detail table
string name = dr.GetString(0);
//I tried to set the text of the checkListBox as the teacherName, but I can't somehow
teacherCheckListBox.Text = name;
}
myConn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
When I run the program like this, it said Conversion failed when converting the varchar value "Excel" to data type int. Is there a way to fix it? it shouldn't be a problem because in my Application_Detail table, my applicationName's and my teacherName's data type is set as nvarchar(50) and applicationId and teacherId = int;
The problem is with this line, I would think:
where aud.applicationId = '" + applicationComboBox.Text +
Based on your code, I would think that applicationId is an int and applicationComboBox.Text is just that, text.
Try this:
where ad.applicationName = '" + applicationComboBox.Text.Trim() +
Try this:
if (string.IsNullOrWhiteSpace(teacherCheckListBox.FindString(name))
{
teacherCheckListBox.Items.Add(name);
}
I retrieve data from Oracle database and populate a gridview. Next, I try to run a query to select some data but I get an error.
Here is the code:
Db.cs:
public static OracleConnection GetConnection()
{
OracleConnection connection = null;
string connectionString = "Data Source=" + Database +
";User ID=" + UserID +
";Password=" + Password +
";Unicode=True";
try
{
connection = new OracleConnection(connectionString);
}
catch (OracleException ex)
{
throw ex;
}
return connection;
}
Parameters are sent from default.aspx.cs:
new Db(database, userID, password);
OracleConnection connection = Db.GetConnection();
main.aspx.cs retrieves all the data:
private OracleConnection connection = new OracleConnection();
private Select select = new Select();
protected void Page_Load(object sender, EventArgs e)
{
Response.Buffer = true;
if (Db.IsLoggedIn())
{
string selectCommand =
"SELECT " + Settings.TABLE + ".* FROM " + Settings.TABLE + " ORDER BY ";
foreach (string ob in Settings.OB) selectCommand += ob + ", ";
Session["Error"] = null;
connection = Db.GetConnection();
select = new Select(ddlBubID, ddlBusArea, ddlDrillSite, ddlWell, connection);
gvData.DataKeyNames = Settings.PK;
gvData.SelectedIndex = -1;
DS.ConnectionString = connection.ConnectionString;
DS.SelectCommand = selectCommand.Remove(selectCommand.Length - 2, 2);
DS.ProviderName = Settings.PROVIDER_NAME;
PopulateFooter(gvData.FooterRow);
}
else
{
Session["Error"] = Settings.ERROR_MESSAGE[0, 0];
Response.Clear();
Response.Redirect("default.aspx");
}
}
public string ToolTip(string column)
{
string value = "";
OracleCommand cmd = new OracleCommand();
cmd.Connection = connection;
cmd.CommandText = "SELECT DISTINCT COMMENTS " +
"FROM SYS.ALL_COL_COMMENTS " +
"WHERE (TABLE_NAME = 'CTD_PROBLEM_EDIT_V') " +
"AND (COLUMN_NAME = " + column + ")";
cmd.CommandType = CommandType.Text;
OracleDataReader reader = cmd.ExecuteReader(); // I get an error here
reader.Read();
value = reader["COMMENTS"].ToString();
reader.Close();
return value;
}
protected void gvData_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
for (int i = 1; i < e.Row.Cells.Count; i++)
{
try
{
LinkButton lb =
(LinkButton)gvData.HeaderRow.Cells[i].Controls[0];
lb.ToolTip = ToolTip(lb.Text);
/* Blah Blah*/
}
catch { }
}
if (e.Row.RowType == DataControlRowType.Footer)
PopulateFooter(e.Row);
}
ToolTip(); throws an error:
Invalid operation. The connection is closed.
EDIT:
This would have been helpful:
Static Classes and Static Class Members
Might not be the problem but this looks weird:
new Db(database, userID, password);
OracleConnection connection = Db.GetConnection();
GetConnection is a static method and thus it does not see any member attributes you might be setting in the constructor (unless they are static as well). If they are all static, consider refactoring your code to use the singleton pattern as it is more readable.
Another thing is that the connection attribute is a member of the page class which is generated for each request (not per application). This means you need either create a new connection in ToolTip method (and any other method that accesses the database) or make the connection attribute static to make it per-application.
Try 2 things:
1.. For your ToolTip() method, the value column to compare for COLUMN_NAME will need to be wrapped properly with single quotes indicating a string/varchar literal value. Likely it's evaluating to COLUMN_NAME = foo when it should be COLUMN_NAME = 'foo'.
cmd.CommandText = "SELECT DISTINCT COMMENTS " +
"FROM SYS.ALL_COL_COMMENTS " +
"WHERE (TABLE_NAME = 'CTD_PROBLEM_EDIT_V') " +
"AND (COLUMN_NAME = '" + column + "')";
2.. Try wrapping your ad-hoc SQL statements in BEGIN and END
3.. Consider refactoring your string building for your SELECT and dynamic ORDER BY clause. That you're doing it on the SelectCommand many lines below isn't obvious to the casual observer or maintainers later in its life.
string selectCommand = string.Format("SELECT {0}.* FROM {0} ORDER BY {1}"
,Settings.TABLE
,string.Join(",",Settings.OB));