Convert textbox to multi-valued, parameterized SQL query - c#

I'm a newbie when it comes to C#, but have some experience with C, Python and MATLAB. I wrote a simple C# program that takes in some user input and converts it into a (parameterized) SQL query. I've successfully converted the datetimepicker into a SQL query; however, I have another parameter (serial numbers) that the user would input into a textbox. They can enter multiple serial numbers, separated by commas. Once the user clicks on 'Submit', the SQL query is sent and the results displayed in a dataGridView.
It works with a single value (i.e. a single serial number), but when I try to put in multiple values, it doesn't work.
I've tried some suggestions like separating the textbox string into an array of values.
private DataTable GetResults()
{
DataTable dtResults = new DataTable();
string connString = ConfigurationManager.ConnectionStrings["dbx"].ConnectionString;
using (SqlConnection con = new SqlConnection(connString))
{
using (SqlCommand cmd = con.CreateCommand())
{
string[] numbers = textBox2.Text.Split(',');
var parameters = new string[numbers.Length];
for (int i = 0; i < numbers.Length; i++)
{
parameters[i] = string.Format("#SN{0}", i);
cmd.Parameters.AddWithValue(parameters[i], numbers[i]);
}
cmd.CommandText = string.Format("SELECT [TestDate],[ParamName],[SerialNumber],[TestDataID],[MeasuredValue]," +
"[MaximumLimit],[MinimumLimit],[PassResult] FROM [dbo].[Device.ParametricTestResults] " +
"WHERE SerialNumber IN ({0}) " +
"AND (TestDate BETWEEN (#start) AND (#end)) " +
"AND PassResult = 1", string.Join(", ", parameters));
cmd.Parameters.AddWithValue("#start", dateTimePicker1.Text);
cmd.Parameters.AddWithValue("#end", dateTimePicker2.Text);
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
dtResults.Load(reader);
}
}
return dtResults;
}
And the 'Submit' button has the following code attached to it:
private void button12_Click(object sender, EventArgs e)
{
TestResultsdataGridView.DataSource = GetResults();
}
Again, the datagridview should display entries for multiple serial numbers, but it only works for one.

Related

Combobox doubles the value when populated by a database

Im using C# Winforms and SQL Server as my database.
In my Combobox_Leave Event, it will populate other Combobox with the text value of the previous
This is one of my Combobox_Leave Event, it is similar with other Combobox
private void cmbPItem_Leave(object sender, EventArgs e)
{
using (SqlConnection conn = new SqlConnection(#"Server=" + ip + "," + port + "; Database=records; User ID=" + sqlid + "; Password=" + sqlpass + ""))
{
conn.Open();
using (SqlDataAdapter sda = new SqlDataAdapter(#"SELECT DISTINCT [Brand]
FROM [dbo].[products] WHERE Item LIKE '" + cmbPItem.Text + "'", conn))
{
DataTable dt = new DataTable();
sda.Fill(dt);
if (dt.Rows.Count != 0)
{
cmbPBrand.Items.Clear();
for (int b = 0; b < dt.Rows.Count; b++)
{
cmbPBrand.Items.Add(dt.Rows[b][0].ToString());
}
}
}
using (SqlDataAdapter sda = new SqlDataAdapter(#"SELECT DISTINCT [Manufacturer]
FROM [dbo].[products] WHERE Item LIKE '" + cmbPItem.Text + "'", conn))
{
DataTable dt = new DataTable();
sda.Fill(dt);
if (dt.Rows.Count != 0)
{
cmbPMan.Items.Clear();
for (int m = 0; m < dt.Rows.Count; m++)
{
cmbPMan.Items.Add(dt.Rows[m][0].ToString());
}
}
}
using (SqlDataAdapter sda = new SqlDataAdapter(#"SELECT DISTINCT [Car]
FROM [dbo].[products] WHERE Item LIKE '" + cmbPItem.Text + "'", conn))
{
DataTable dt = new DataTable();
sda.Fill(dt);
if (dt.Rows.Count != 0)
{
cmbPCar.Items.Clear();
for (int i = 0; i < dt.Rows.Count; i++)
{
cmbPCar.Items.Add(dt.Rows[i][0].ToString());
}
}
}
using (SqlDataAdapter sda = new SqlDataAdapter(#"SELECT DISTINCT [Year]
FROM [dbo].[products] WHERE Item LIKE '" + cmbPItem.Text + "'", conn))
{
DataTable dt = new DataTable();
sda.Fill(dt);
if (dt.Rows.Count != 0)
{
cmbPYr.Items.Clear();
for (int y = 0; y < dt.Rows.Count; y++)
{
cmbPYr.Items.Add(dt.Rows[y][0].ToString());
}
}
}
conn.Close();
}
}
And the output is like this
When the user click on the second Combox, in this example the cmbPBrand. It populates the Combobx with duplicated values. But when the user click another Combobox, not choosing any entry from cmbPBrand. The values are not duplicated.
Another example of duplicated values.
In this the cmbPYr is clicked after the selection from the cmbPItem. It duplicates the DISTINCT values.
Note that this happens when the user CLICK the second Combobox. And Im using Leave Event for my Combobox.
I also tried adding MouseClick and MouseDown and Enter and SelectedIndexChanged Events. But it still duplicate the values.
EDIT:
When using the query
SELECT DISTINCT Brand,Manufacturer,Car,Year FROM [dbo].[products] WHERE Item LIKE 'BRAKE PADS'
Where cmbPItem.Text, for example, is BRAKE PADS.
It will query almost 675 rows.
EDIT: As for Kevin suggestion. This is code is for Brand ComboBox only, but it still show duplicate values.
private void cmbProd_Enter(object sender, EventArgs e) {
itemValue(cmbPItem.Text); }
private void itemValue(string sitem) {
getBrand(sitem); }
private void getBrand(string sitem) {
using (SqlCommand cmd = new SqlCommand(#"SELECT DISTINCT [Brand] FROM [dbo].[products] WHERE Item = #Item"))
{
cmd.Parameters.Add(new SqlParameter("Item", sitem));
populateBrand(cmbPBrand, cmd);
} }
private void populateBrand(ComboBox cmb, SqlCommand cmd) {
using (SqlConnection conn = new SqlConnection(#"Server=" + ip + "," + port + "; Database=records; User ID=" + sqlid + "; Password=" + sqlpass + ""))
{
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
cmd.Connection = conn;
DataTable dt = new DataTable();
sda.Fill(dt);
if (dt.Rows.Count != 0)
{
cmb.Items.Clear();
for (int b = 0; b < dt.Rows.Count; b++)
{
cmb.Items.Add(dt.Rows[b][0].ToString());
}
}
conn.Close();
}
} }
I'm going to suggest tackling the problem from a slightly different angle.
First up, you definitely should think about changing those queries to be parameterized. Like I commented, any time you put raw input directly into a SQL statement, you're opening the door to SQL Injection Attacks. Even if it's not based on user input, it's still a bad habit to get into. Doing SQL parameterization isn't hard - it's just one extra line of code.
Next up: Refactor your code. If I understand you correctly, your code reads like:
Event X
{
13 or so lines to update Combo Box #1
13 or so lines to update Combo Box #2
13 or so lines to update Combo Box #3
13 or so lines to update Combo Box #4
}
Event Y
{
13 or so lines to update Combo Box #1
13 or so lines to update Combo Box #2
13 or so lines to update Combo Box #3
13 or so lines to update Combo Box #4
}
Event Z
{
13 or so lines to update Combo Box #1
13 or so lines to update Combo Box #2
13 or so lines to update Combo Box #3
13 or so lines to update Combo Box #4
}
Event ... etc
Do some googling and playing around with the Single Responsibility Principle (SRP) - it'll help you write cleaner, easier-to-debug code.
When that's said and done? Then you've got a good way of figuring out what the problem is: put some debug lines in your "UpdateBrandCombo()" function - the only place where the Brand combo box is updated (right now, you've got a problem in that any of those events might be updating the combo box, and you don't really have any good way of figuring out what's doing it.)
Something like:
Event X
{
UpdateCombosWithSearch(cmbPItem.Text);
}
// ... later on ...
private void UpdateCombosWithSearch(string searchTerm)
{
UpdateBrandCombo(searchTerm);
UpdateMfgCombo(searchTerm);
UpdateCarCombo(searchTerm);
}
private void UpdateBrandCombo(string searchTerm)
{
SqlCommand sqlCmd = new SqlCommand("select distinct car from dbo.products where Item like #item");
sqlCmd.Parameters.Add(new SqlParameter("item", searchTerm));
SetComboBoxUsingQuery(cmbPBrand, sqlCmd);
}
private void SetComboBoxUsingQuery(ComboBox cbx, SqlCommand sqlCmd)
{
cbx.Items.Clear();
// code to get a DataTable from the sqlCmd
// code to read the DataTable and add items to cbx
}
See the beauty? You don't have repetitive code. Your events all have one line: UpdateCombosWithSearch(). UpdateCombosWithSearch simply calls an Update on each combo box it needs to update. And each of those functions simply generate an SQL command and pass in which box is to be updated. The only function that even has any SQL code is the SetComboBoxUsingQuery() function.
So now you can add something like:
System.Diagnostics.Debug.WriteLine("Event logged by " + (new System.Diagnostics.StackTrace()).ToString());
... to one of those functions - so you can figure out just where/when/how your update code is being called.

Keyword based search in asp.net mvc application

I was doing a keyword based search in an asp.net mvc application from a sql database.
The database has a table Resources which has entries of the following format:
resource
english pdf
maths elementary book
english vocabulary
The user is then asked to enter a query which generates the resource which matches the query:
e.g. The user enters "Get all english books"
query = "Get all english books";
I first tokenise the query string and push the contents into an array:
string[] keywords = query.Split(' ');
I do a keyword based match with all the keywords with all the entries in the table. If any of the keywords are present in any of the resources I return that row.
Since I don't know what would be the number of keywords prior, I have to write a dynamic query string. Here is the code that I have written:
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
// Tokenize the query
String[] tokens = searchQuery.Split(' ');
if (tokens.Length != 0) {
string query = "SELECT * FROM Queries WHERE query LIKE '(%'" + "#0" + "'%)'";
for (int i = 1; i < tokens.Length; i++)
query += " OR query LIKE '(%'" + "#" + i + "'%)'";
query += ";";
Console.WriteLine("The query is : " + query);
Console.ReadLine();
SqlCommand sqlCommand = new SqlCommand(query, sqlConnection);
sqlCommand.CommandType = System.Data.CommandType.Text;
for (int i = 0; i < tokens.Length; i++)
sqlCommand.Parameters.AddWithValue("#"+i, tokens[i]);
using (SqlDataReader reader = sqlCommand.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine("{0}", reader[1]);
}
}
}
This does not generate the expected output. Can somebody has experience with this.

show suggestions on text box

i am working on an sale invoice in sale invoice i am auto filling the data about product in its relevant fields, like when user enters product code in product code text box the product name and product price text boxes automatically fills themselves by retrieving data from DB, i want that when user starts type code here the program give the suggestions about all the products in the database. like when user enter 1 the program give suggestion about product codes, product codes starting with 1 show themselves and the user just selects the one he wants to.
the code I've done on text change event of product code text box is
private void textBox2_TextChanged(object sender, EventArgs e)
{
if (txtProductCode1.Text == "")
{
txtProductName1.Text = "";
txtQty.Text = "";
txtSalePrice.Text = "";
txtTotal.Text = "";
}
string sql = "select productprice, ProductName";
sql += " from dbo.productlog";
sql += " where productCode = '" + txtProductCode1.Text + "'"; // Placing ProductCode in single quotes because it's not an int column, but a varchar column, in SQL server
SqlConnection cn = new SqlConnection();
SqlCommand rs = new SqlCommand();
SqlDataReader sdr = null;
clsConnection clsCon = new clsConnection();
clsCon.fnc_ConnectToDB(ref cn);
rs.Connection = cn;
rs.CommandText = sql;
sdr = rs.ExecuteReader();
if (sdr.Read())
{
txtProductName1.Text = sdr["ProductName"].ToString();
txtSalePrice.Text = sdr["ProductPrice"].ToString();
}
else if (txtProductName.Text == "")
{
goto exitPoint;
}
else if (!sdr.Read())
{
MessageBox.Show("Data not found", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
txtProductName.Focus();
}
exitPoint:
sdr.Close();
rs = null;
cn.Close();
}
how can i show suggestion about product codes in text box?
EDIT:
Its no a windform app means it's a desktop based app and i am creating it in C#.net using VS2010
check this , hope this will work for you
http://msdn.microsoft.com/en-us/library/system.windows.forms.textbox.autocompletemode%28v=vs.110%29.aspx

Split text and insert words in sql database

I want to select file contains .txt and split all strings in each text into array
then insert the divided words into sql database (word, counter) and count the repeated words in each text by counter that lead to unrepeated words in database tables>>
(1)-counter code is incorrect I found several errors in my code >> (i want to prevent a repeat of word at the same time calculate how many times repeated word in databases ,by using counter.)
(2)- my code has static path (just one text ),but I want user to select his file which he want to split. (browse.. button)
(3-)sql database could not show Arabic Words (?????)
namespace lib123
{
public partial class Form1 : Form
{
SqlConnection sqlConn;
SqlCommand sqlComm;
SqlDataAdapter sqlAdptr;
public Form1()
{
InitializeComponent();
sqlConn = new SqlConnection();
sqlComm = new SqlCommand();
sqlAdptr = new SqlDataAdapter();
sqlComm.Connection = sqlConn;
sqlComm.CommandType = CommandType.Text;
sqlConn.ConnectionString = "Data Source=007-PC\\SQLEXPRESS ;Initial Catalog= Email_DB;Integrated Security =True ";
}
private void Form1_Load(object sender, EventArgs e)
{
FillGrid();
}
private void button1_Click(object sender, EventArgs e)
{
if (sqlConn.State != ConnectionState.Open)
sqlConn.Open();
// sqlComm = sqlConn.CreateCommand();
StreamReader streamReader = new StreamReader(#"C:\Users\007\Desktop\spam-email\spamenglish.txt"); //get the file
string stringWithMultipleSpaces = streamReader.ReadToEnd(); //load file to string
streamReader.Close();
Regex r = new Regex(" +"); //specify delimiter (spaces)
string[] words = r.Split(stringWithMultipleSpaces); //(convert string to array of words)
int c = 1;
string strQry = "select ISNULL( max(id),0) as id from word_tb ";
sqlComm.CommandText = strQry;
int LastID = int.Parse(sqlComm.ExecuteScalar().ToString());
string x ;
String st = null;
for (int i = 0; i < words.Length; i++)
{
string y = words[i];
for (int j = 0; j <LastID; j++)
{
x = "select word from word_tb where id = j";
sqlComm.CommandText = x ;
if (x.Equals(y))
{
c = c + 1;
string sql = "INSERT INTO word_tb (count) VALUES ('" + c + "') where id = i";
sqlComm.CommandText = sql;
}
else
{
LastID = LastID + 1;
st += "INSERT INTO word_tb(id, word,count) VALUES('" + LastID + "', '" + words[i].ToString() + "','" + c + "');";
//st += "INSERT INTO word_tb(word) VALUES('" + words[i].ToString() + "');";
}
}
}
sqlComm.CommandType = CommandType.Text;
sqlComm.CommandText = st;
sqlComm.ExecuteNonQuery();
FillGrid();
}
private void FillGrid()
{
DataTable tbl = new DataTable();
string strQry = "select * from word_tb ";
sqlComm.CommandText = strQry;
sqlAdptr.SelectCommand = sqlComm;
sqlAdptr.Fill (tbl) ;
dataGridView1.DataSource = tbl;
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
//private void btnDelete_Click(object sender, EventArgs e)
//{
// string str = "DELETE FROM word_tb";
// sqlComm.CommandType = CommandType.Text;
// sqlComm.CommandText = str;
// sqlComm.ExecuteNonQuery();
// dataGridView1.Rows.Clear();
// }
}
}
1-counter code is incorrect I found several errors in my code?
you can use below code to split the File Text into words based on space as delimiter.
Code:
String strAllData = System.IO.File.ReadAllText(#"C:\Users\007\Desktop\spam-email\spamenglish.txt");
String[] words = strAllData.Split(' ');
2- my code has static path (just one text ),but I want user to select
his file which he want to split. (browse.. button) ?
you can use OpenFileDialog control to let user choose the file which he/she wants to work on.
Code:
OpenFileDialog fileDialog = new OpenFileDialog();
if (fileDialog.ShowDialog() == DialogResult.OK)
{
String strAllData = System.IO.File.ReadAllText(fileDialog.FileName);
String[] words = strAllData.Split(' ');
}
3 -sql database could not show Arabic Words (?????) ?
Sql Server can not show Uni Code characters when you fire a SELECT Query because you have created your table columns/feilds as varchar.
Solution: if you want to get the Arabic characters when you fire a SELECT query you should create your table columns to accept Uni Code characters using NVARCHAR datatype instead of VARCHAR. N stands for National language character set.
Step1 : create your table columns as NVARCHAR as below:
create table sample(
[name] [nvarchar](100) NOT NULL)
Step 2: Use N as prefix while inserting Data into NVARCHAR columns. N as prefix tells that all following characters are Uni Code characters.
Code:
INSERT INTO sample VALUES(N'لا أتكلم العربية');
Now if you fire a SELECT Query you will be able to see the Arabic Characters.

asp.net, C# passing list i in the query

i have the code of passing a selected value in the the query and that value will bind the data in the girdview. the selection is made with the Listbox..
I want to pass a list param of S_ID
Now I want to modify my program a little i want to pass a list of param. in the query.. so that this can enable multiple selection list in the listbox.. I've searched over Internet and i couldnt find a certain satisfying answer... I'm not very good at query.
protected void Button2_Click(object sender, EventArgs e)
{
OleDbConnection con = new OleDbConnection();
con.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Database11.accdb";
con.Open();
for (int i = 0; i < ListBox1.Items.Count; i++)
//foreach(Items Item in Listbox1)
{
if (ListBox1.Items[i].Selected == true)
{
string Skill_ID = ListBox1.Items[i].Value;
string query1 = "SELECT *FROM Emp AS E, Junction AS J WHERE E.E_ID=J.E_ID And J.S_ID=#Skill_ID";
OleDbCommand cmd1 = new OleDbCommand(query1, con);
cmd1.Parameters.AddWithValue("#Skill_ID", Skill_ID);
OleDbDataReader rs = cmd1.ExecuteReader();
if (rs.HasRows)
{
GridView1.DataSource = rs;
GridView1.DataBind();
rs.Close();
}
//use LINQ to obtain the selected id values as strings
var selectedItems = ListBox1.Items.Cast<ListItem>().Where(p => p.Selected == true).Select(p => p.Value).ToList();
//now concat them as a comma seperated string
var idCommaList = string.Join(', ', selectedItems);
//Now use a WHERE IN () statement instead with your query and concat your comma seperated list of ids into the sql statement
var query1 = #"SELECT *
FROM Emp AS E, Junction AS J
WHERE E.E_ID = J.E_ID AND J.S_ID IN (" + idCommaList + ")";

Categories