How to validate winforms field for uniqueness - c#

I have code that checks for unique values when the user updates an ID field, but I am so new I am wondering if there is a better way.
private void tbPrinterID_Validating(object sender, CancelEventArgs e)
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.LazerMaintenance_Conn))
{
try
{
string query = "SELECT COUNT(*) as Count FROM Printers WHERE PrinterID = '" + tbPrinterID.Text + "'";
SqlDataAdapter da = new SqlDataAdapter(query, conn);
DataTable dt = new DataTable();
da.Fill(dt);
if ((Int32)dt.Rows[0]["Count"] > 0)
{
MessageBox.Show("There is already a printer with ID = " + tbPrinterID.Text);
}
}
catch (Exception ex)
{
MessageBox.Show("Error occured! : " + ex);
}
}
}

Your example is vulnerable to SQL injection, I suggest reading this What are good ways to prevent SQL injection?.
You can make the query a bit more idiomatic:
var sql = "SELECT 1 FROM Printers WHERE PrinterID = #IdToCheck";
using (var command = new SqlCommand(sql, con))
{
command.Parameters.AddWithValue("#IdToCheck", tbPrinterID.Text);
con.Open();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
..........
}
}
}

Related

How can I Store SQL Server Query Results into a List of String?

I want to store what's returned from a database query into a list of string. I've got this code:
List<String> slDistinctUncommonWords = new List<string>();
. . .
slDistinctUncommonWords = GetDistinctWordsFromDB();
. . .
private List<String> GetDistinctWordsFromDB()
{
List<String> slDistinctWords = new List<string>();
try
{
string sQuery = "SELECT DISTINCT UncommonWord " +
"FROM WORDSTATS " +
"ORDER BY UncommonWord";
SqlConnection sqlConnection = new SqlConnection(connection);
SqlCommand cmd = new SqlCommand(sQuery, sqlConnection);
sqlConnection.Open();
slDistinctWords = (List<String>)cmd.ExecuteScalar();
sqlConnection.Close();
return slDistinctWords;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}
The "slDistinctUncommonWords = GetDistinctWordsFromDB();" line fails, though, with "Unable to cast object of type 'System.String' to type 'System.Collections.Generic.List'1[System.String]'".
You could use ExecuteReader instead of ExecuteScalar, like the following code:
using(SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
slDistinctWords.Add(reader["UncommonWord"].ToString());
}
}
I hope you find this helpful.
Put into a datatable
DataTable dt = new DataTable();
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
adapter.Fill(dt);
List<string> slDistinctWords = dt.AsEnumerable().Select(x => x.Field<string>(0)).Distinct().ToList();
A SqlDataReader can be treated as a collection of IDataRecord objects. So
var col = new List<String>();
using (var rdr = cmd.ExecuteReader())
{
col = rdr.Cast<IDataRecord>().Select(r => r.GetString(0)).ToList();
}
If you are using Microsoft SQL Server, try to replace your SQL query statement with this:
string sQuery = "SELECT DISTINCT CAST(UncommonWord AS VARCHAR(32)) + ',' " +
"FROM WORDSTATS " +
"ORDER BY UncommonWord FOR XML PATH('')";
This works:
private List<String> GetDistinctWordsFromDB()
{
List<String> slDistinctWords = new List<string>();
try
{
string sQuery = "SELECT DISTINCT UncommonWord " +
"FROM WORDSTATS " +
"ORDER BY UncommonWord";
SqlConnection sqlConnection = new SqlConnection(connection);
SqlCommand cmd = new SqlCommand(sQuery, sqlConnection);
SqlDataReader reader;
sqlConnection.Open();
reader = cmd.ExecuteReader();
while (reader.Read())
{
slDistinctWords.Add(reader.GetString(0));
}
reader.Close();
sqlConnection.Close();
return slDistinctWords;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}

Calling (ID_number) primary key to textbox using Combobox (Category Description)

Dealing with Foreign Key using ms access in C#.
Each time I select the Category Description(CatDesc) using combobox from category table, I wanted to get/call automatically the Category Id(CatID) in the textbox1.
My code doesn't work, and no errors given.
This is my sample code:
private void cmdcategoryy_TextChanged(object sender, EventArgs e)
{
CategoryDesc();
}
void CategoryDesc()
{
OleDbConnection mycon = new OleDbConnection(#"Provider = Microsoft.ACE.OLEDB.12.0; Data Source = C:\Users\BlaBla\Desktop\Docsmonitorg\Try 081517\WindowsFormsApp6\WindowsFormsApp6\Database.accdb");
string con;
try
{
con = "Select CatID, CatDesc from Category where CatDesc = '" + cmdcategoryy.Text + "' ";
mycon.Open();
OleDbCommand cm = new OleDbCommand();
OleDbDataAdapter da = new OleDbDataAdapter();
DataTable mydata1 = new DataTable();
cm.CommandText = con;
cm.Connection = mycon;
int i;
da.SelectCommand = cm;
da.Fill(mydata1);
for (i = 0; i <= mydata1.Rows.Count - 1;)
textBox1.Text = (mydata1.Rows[i]["CatID"].ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
mycon.Close();
mycon.Dispose();
}
}
Here is the design
This is my Database
Sample:
Category Description has Graphic Designer, AutoCat, AX Staff
Category ID 1,2,3
I will hide that textbox1.

C# ADO.NET: check for existing index

I have the following code and I want to show an error message if the id is not found in the table can any body help?
private void button4_Click(object sender, EventArgs e)
{
conn = new MySqlConnection(cs);
string sql = "select * from question where id=#id;";
MySqlCommand cmd = new MySqlCommand(sql, conn);
conn.Open();
cmd.Prepare();
cmd.Parameters.AddWithValue("#id", int.Parse(textBox1.Text));
MySqlDataReader rd = cmd.ExecuteReader();
string res = "";
while (rd.Read())
{
if (rd.HasRows==true)
{
res = string.Format("id={0} pid={1} question={2}", rd.GetInt32(0), rd.GetInt32(1), rd.GetString(2));
MessageBox.Show("found" + "\n" + res);
}
MessageBox.Show(" id not found");
}
You need to check for has rows before to start iterating the reader.
if (rd.HasRows==true)
{
while (rd.Read())
{
// Do something here
}
}
else
{
// Show message here
}

C# SQL Server CE - Update won't work

I'm trying to finish a college project that requires a program to interact with a database.
Some of my naming is a little odd, but don't worry!
I'm trying to use a single submit button to either update or insert to the database.
Main issue is that I can't get an update to work though when I changed my code to try and fix it, I made it worse. Here is what I currently have.
private void btn_submit_Click(object sender, EventArgs e)
{
using (SqlCeConnection con = new SqlCeConnection(#"Data Source=G:\Dropbox\HND\Visual Studio\Visual C#\TestForms\TestForms\Database1.sdf"))
{
con.Open();
string taskSel = "SELECT TaskCode FROM TaskCode;";
SqlCeCommand c1 = new SqlCeCommand(taskSel, con);
SqlCeDataReader reader;
reader = c1.ExecuteReader();
if (reader.Read())
{
try
{
string taskUpdate = "UPDATE TaskCode SET TaskCode = #TaskCode, TaskDescription = #TaskDescription = WHERE TaskCode = #TaskCode;";
SqlCeCommand c = new SqlCeCommand(taskUpdate, con);
c.Parameters.AddWithValue("#TaskCode", cbx_taskCode.Text);
c.Parameters.AddWithValue("#TaskDescription", txt_desc.Text);
c.ExecuteNonQuery();
con.Close();
MessageBox.Show("Record has been updated");
MainMenu.Current.Show();
this.Close();
}
catch (SqlCeException exp)
{
MessageBox.Show(exp.ToString());
}
}
else
{
try
{
string taskInsert = "INSERT INTO TaskCode VALUES (#TaskCode, #TaskDescription);";
SqlCeCommand c = new SqlCeCommand(taskInsert, con);
c.Parameters.AddWithValue("#TaskCode", cbx_taskCode.Text);
c.Parameters.AddWithValue("#TaskDescription", txt_desc.Text);
c.ExecuteNonQuery();
con.Close();
MessageBox.Show("Record has been added");
MainMenu.Current.Show();
this.Close();
}
catch (SqlCeException exp)
{
MessageBox.Show(exp.ToString());
}
}
}
}
Has anyone got any ideas why I am getting an error on the c.ExecuteQuery line?
If I remove said line, it will not throw an exception, but it will not update the database.
Thanks
You have a simple syntax error in your update query just before the where statement.
There is an invalid equal sign
string taskUpdate = "UPDATE TaskCode SET TaskCode = #TaskCode, " +
"TaskDescription = #TaskDescription " +
"WHERE TaskCode = #TaskCode;";
Your query also could be simplified with
using (SqlCeConnection con = new SqlCeConnection(#"Data Source=G:\Dropbox\HND\Visual Studio\Visual C#\TestForms\TestForms\Database1.sdf"))
{
con.Open();
string taskSel = "SELECT COUNT(*) FROM TaskCode";
string cmdText;
SqlCeCommand c1 = new SqlCeCommand(taskSel, con);
int count = (int)c1.ExecuteScalar();
if (count > 0)
{
// Here there is no point to update the TaskCode. You already know the value
// Unless you have a different value, but then you need another parameter
// the 'old' TaskCode.....
cmdText = "UPDATE TaskCode SET " +
"TaskDescription = #TaskDescription " +
"WHERE TaskCode = #TaskCode;";
}
else
{
cmdText = "INSERT INTO TaskCode VALUES (#TaskCode, #TaskDescription);";
}
try
{
SqlCeCommand c = new SqlCeCommand(cmdText, con);
c.Parameters.AddWithValue("#TaskCode", cbx_taskCode.Text);
c.Parameters.AddWithValue("#TaskDescription", txt_desc.Text);
c.ExecuteNonQuery();
MessageBox.Show(count > 0 ? "Record has been updated" : "Record has been added");
MainMenu.Current.Show();
this.Close();
}
catch (SqlCeException exp)
{
MessageBox.Show(exp.ToString());
}
}
Not sure if it is the only problem, but you have an equal (=) sign before the WHERE keyword.

C# SQL query returns nothing

I am trying to get my Winforms app to query a SQL Server CE database and return all rows that correspond to the column name specified by the user through a drop down list. When I run the programs it will return just a blank dataGrid. This is my first time working with SQL Server CE so any help would be appreciated.
My code is:
private void srchBTN_Click(object sender, EventArgs e)
{
string conString = Properties.Settings.Default.CurricularChangeTrackerConnectionString;
using (SqlCeConnection conn = new SqlCeConnection(conString))
{
string queryString = ("SELECT * FROM SecondaryEducation WHERE ProgramCode='" + PrgmCde.SelectedValue + "'");
try
{
conn.Open();
using (SqlCeDataAdapter adapter = new SqlCeDataAdapter(queryString, conn))
{
DataTable table = new DataTable();
adapter.Fill(table);
dataGridView1.DataSource = table;
adapter.Dispose();
}
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
If a property is not specified in ValueMember, SelectedValue returns the results of the ToString method of the object.
My point is you may not be getting what you think from the comboBox.
Try this:
string queryString = ("SELECT * FROM SecondaryEducation WHERE ProgramCode='" + PrgmCde.Items[PrgmCde.SelectedIndex].ToString() + "'");
You are declaring the data table inside the using statement, try this
private void srchBTN_Click(object sender, EventArgs e)
{
string conString = Properties.Settings.Default.CurricularChangeTrackerConnectionString;
DataTable table = new DataTable();
using (SqlCeConnection conn = new SqlCeConnection(conString))
{
string queryString = ("SELECT * FROM SecondaryEducation WHERE ProgramCode='" + PrgmCde.SelectedValue + "'");
try
{
conn.Open();
using (SqlCeDataAdapter adapter = new SqlCeDataAdapter(queryString, conn))
{
adapter.Fill(table);
dataGridView1.DataSource = table;
adapter.Dispose();
}
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
That way the table wont be disposed of when the scope of the using statement is ended.

Categories

Resources