How to clear datatable values when using two datatables? - c#

I have two DataTables after passing query the second DataTable Shows the FirstDataTable values. Please find my code
My connection class is
public class Connection
{
conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString);
public SqlDataAdapter ad;
public DataTable dt = new DataTable();
public DataTable gettable(string cmdtxt)
{
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
conn.Open();
dt.Clear();
ad = new SqlDataAdapter(cmdtxt, conn);
ad.Fill(dt);
return dt;
}
}
My code is
String qry="";
DataTable shiftdt = new DataTable();
DataTable empdt = new DataTable();
qry = "select ShiftID from ShiftGroup where ShiftName="#Shift";
shiftdt = conn.gettable(qry);
qry = "select EmpCode from EmployeeShift where GroupCode="#gcode";
empdt = conn.gettable(qry);
First,shiftdt shows proper output ShiftID and when go ahead empdt shows first column as ShiftID and Second Column as EmpCode. Actually I dont want ShiftID in empdt. And again when I go ahead Shiftdt values changes to EmpCode. May I know the reason?
I tried `Dot net learner,when I change code as per him, I have a
dropdown class it shows error like
`Error 8 'Sample.Connection' does not contain a definition for 'dt' and no extension method 'dt' accepting a first argument of type 'Sample.Connection' could be found (are you missing a using directive or an assembly reference?
. That calss is
public class Dropdown
{
Connection con = new Connection();
public void dropdwnlist(string qry, DropDownList ddl)
{
con.gettable(qry);
if (con.dt.Rows.Count > 0)
{
if (con.dt.Columns.Count == 2)
{
string str1 = con.dt.Columns[0].ColumnName.ToString();
string str2 = con.dt.Columns[1].ColumnName.ToString();
ddl.DataValueField = str1;
ddl.DataTextField = str2;
ddl.DataSource = con.dt;
ddl.DataBind();
con.dt.Columns.Remove(str1);
con.dt.Columns.Remove(str2);
}
else
{
string str = con.dt.Columns[0].ColumnName.ToString();
ddl.DataValueField = str;
ddl.DataTextField = str;
ddl.DataSource = con.dt;
ddl.DataBind();
con.dt.Columns.Remove(str);
}
}
ddl.Items.Insert(0, ("--Select--"));
}
}

You Have dt as Global variable in Class So Please Make it Local variable for Function or Assign new DataTable on starting of gettable function.
Your revised Code should be
public class Connection
{
conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString);
public SqlDataAdapter ad;
public DataTable gettable(string cmdtxt)
{
DataTable dt = new DataTable();
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
conn.Open();
dt.Clear();
ad = new SqlDataAdapter(cmdtxt, conn);
ad.Fill(dt);
return dt;
}
}
I had revised code as per your need please check it.
You shouldn't use Connection Class DataTable(dt) Variable to bind dropdown instead Declare DataTable Variable Local for Dropdown Class and use it to bind Dropdown.
Revised Code for Dropdown Class
public class Dropdown
{
Connection con = new Connection();
public void dropdwnlist(string qry, DropDownList ddl)
{
DataTable dt =con.gettable(qry);
if (dt.Rows.Count > 0)
{
if (dt.Columns.Count == 2)
{
string str1 = dt.Columns[0].ColumnName.ToString();
string str2 = dt.Columns[1].ColumnName.ToString();
ddl.DataValueField = str1;
ddl.DataTextField = str2;
ddl.DataSource = dt;
ddl.DataBind();
dt.Columns.Remove(str1);
dt.Columns.Remove(str2);
}
else
{
string str = dt.Columns[0].ColumnName.ToString();
ddl.DataValueField = str;
ddl.DataTextField = str;
ddl.DataSource = dt;
ddl.DataBind();
dt.Columns.Remove(str);
}
}
ddl.Items.Insert(0, ("--Select--"));
}
}

Related

protected DataSet against SQL Inejection

I want to create a class that I can get datatable of specific table given in the parameter of the constructor.
But how I can do it without it being vulnerable to SQL Injections?
I would've done something like this: (But you can't use those statements like that)
public class SqlClass
{
DataTable dt;
string table;
public SqlClass(String table)
{
this.table = table;
SqlConnection c = new SqlConnection();
c.conOpen();
MySqlCommand msc = new MySqlCommand("SELECT * FROM #tableName", c.Con); //Cant do that
msc.Parameters.AddWithValue("#tableName", table);
DataSet ds = c.getDataSet(msc, table);
this.dt = ds.Tables[table];
c.conClose();
}
public DataTable Dt { get => dt; set { dt = value; } }
}
Any other working alternative that won't harm me? Thanks.

Set value of combo box to collected value from source

I have a form with two combo boxes which both have a list from a database. In this case one is a list of countries and based on the value selected there, the second list is updated to show only the cities that belong to the selected country. After that, the values are combined and stored in my program like "city, country".
When I open my form I retrieve that information and separate the values back to just country and city. All working. The trouble I have now is that the comboboxes should display the retrieved values if the correspond to a value found in the list/database. I tried as shown below, but that is not working. I guess it has something to do with adding a new row to the database to show "--Select Country--" and "--Select City--".
I hope you can point me in the right direction. Thank you all in advance for your replies.
comboBoxCountry.SelectedValue = comboBoxCountry.FindString(country);
comboBoxCity.SelectedValue = comboBoxCity.FindString(city);
public partial class FormPropertyEditor : Form
{
//Connect to local database.mdf
SqlConnection con = new SqlConnection("Data Source = (LocalDB)\\MSSQLLocalDB;AttachDbFilename=" +
#"C:\Users\gleonvanlier\AppData\Roaming\Autodesk\ApplicationPlugins\MHS Property Editor\Database.mdf;" +
"Integrated Security=True;Connect Timeout=30;User Instance=False;");
DataRow dr;
public FormPropertyEditor()
{
InitializeComponent();
ReadProperties();
refreshdata();
}
public void refreshdata()
{
con.Open();
SqlCommand cmd = new SqlCommand("select * from TblCountries Order by CountryName", con);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
sda.Fill(dt);
con.Close();
dr = dt.NewRow();
dr.ItemArray = new object[] { 0, "--Select Country--" };
dt.Rows.InsertAt(dr, 0);
comboBoxCountry.ValueMember = "CountryID";
comboBoxCountry.DisplayMember = "CountryName";
comboBoxCountry.DataSource = dt;
comboBoxCountry.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
comboBoxCountry.AutoCompleteSource = AutoCompleteSource.ListItems;
}
private void comboBoxCountry_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBoxCountry.SelectedValue.ToString() != null)
{
int CountryID = Convert.ToInt32(comboBoxCountry.SelectedValue.ToString());
refreshstate(CountryID);
}
}
public void refreshstate(int CountryID)
{
con.Open();
SqlCommand cmd = new SqlCommand("select * from TblCities where CountryID= #CountryID Order by CityName", con);
cmd.Parameters.AddWithValue("CountryID", CountryID);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
sda.Fill(dt);
con.Close();
dr = dt.NewRow();
dr.ItemArray = new object[] { 0, 0, "--Select City--" };
dt.Rows.InsertAt(dr, 0);
comboBoxCity.ValueMember = "CityID";
comboBoxCity.DisplayMember = "CityName";
comboBoxCity.DataSource = dt;
comboBoxCity.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
comboBoxCity.AutoCompleteSource = AutoCompleteSource.ListItems;
}
private void ReadProperties()
{
string progId = "Inventor.Application";
Type inventorApplicationType = Type.GetTypeFromProgID(progId);
Inventor.Application invApp = (Inventor.Application)Marshal.GetActiveObject(progId);
//Get the active document in Inventor
Document oDoc = (Document)invApp.ActiveDocument;
ReadProperties readProperties = new ReadProperties();
//Read Customer
string txtCustomer = readProperties.ReadCustomProperty("Customer", oDoc).ToString();
this.textBoxCustomer.Text = txtCustomer;
//Read Location
string txtLocation = readProperties.ReadCustomProperty("Location", oDoc).ToString();
try
{
string[] location = txtLocation.Split(',', ' ');
string city = location[0];
string country = location[1];
comboBoxCountry.SelectedValue = comboBoxCountry.FindString(country);
comboBoxCity.SelectedValue = comboBoxCity.FindString(city);
}
catch (Exception e)
{
string city = string.Empty;
string country = string.Empty;
}
}
This solved it:
comboBoxCountry.SelectedIndex = comboBoxCountry.FindStringExact(country);
comboBoxCity.SelectedIndex = comboBoxCity.FindStringExact(city);

Compare Selected Date and Database Date

My logic is:
"if selected date is a match with the database date from Holiday table, return message as "OK"
I have already formatted date in the code shown below. When I do test with hardcoded database date, the code works fine.
How to get database date from my Holiday table?
PS: Holiday table includes different dates so system needs to loop and search every row in Holiday table.
Code:
[System.Web.Services.WebMethod]
public static string GetDateFromDB(DateTime compareDate)
{
string selectedDate = compareDate.ToString("yyyy/MM/dd");
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LoginDBConnectionString1"].ConnectionString);
SqlCommand com = new SqlCommand("SELECT * from Holiday", conn);
SqlDataAdapter sqlDa = new SqlDataAdapter(com);
DataTable dt = new DataTable();
sqlDa.Fill(dt);
//hardcoded is ok
string dbDateString = "2019-02-20";
DateTime date1 = DateTime.ParseExact(dbDateString.Split(' ')[0], "yyyy/MM/dd", null);
string dateDB = date1.ToString("yyyy/MM/dd");
if (dateDB == selectedDate)
{
return "OK";
}
else
{
return "NG";
}
}
string selectedDate = compareDate.ToString("yyyy/MM/dd");
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LoginDBConnectionString1"].ConnectionString);
SqlCommand com = new SqlCommand("SELECT * from Holiday where Date='" + selectedDate + "'", conn);
SqlDataAdapter sqlDa = new SqlDataAdapter(com);
DataTable dt = new DataTable();
sqlDa.Fill(dt);
if (dt == null || dt.Rows.Count() == 0)
return "NG";
else
return "OK";
You said you have multi rows so you just can return "OK" or "NG" after loop all row (or break when have error):
[System.Web.Services.WebMethod]
public static string GetDateFromDB(DateTime compareDate)
{
string selectedDate = compareDate.ToString("yyyy/MM/dd");
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LoginDBConnectionString1"].ConnectionString);
SqlCommand com = new SqlCommand("SELECT * from Holiday", conn);
SqlDataAdapter sqlDa = new SqlDataAdapter(com);
DataTable dt = new DataTable();
sqlDa.Fill(dt);
if (dt != null && dt.Rows.Count > 0)
{
string formatDate = "yyyy/MM/dd";
foreach (DataRow dr in dt.Rows)
{
string dateString = dr["yourColumnName"].ToString();
if (string.IsNullOrEmpty(dateString))
{
continue; // Or set error or something
}
dateString = DateTime.ParseExact(dateString.Split(' ')[0], formatDate, null).ToString(formatDate);
if (dateString.Equals(compareDate))
{
// Do something
}
else
{
// Set error message or something
}
}
// Check after loop and return "OK" or "NG"
}
}

Populating ComboBox from SQL in C#

I am trying to populate my combobox from sql but when i assign a value member to it, it gives me the following error
cannot explicitly convert int into string
Could you help me understand and correct my mistake?
void Fillcombo()
{
string query_select = "SELECT * FROM department";
DataTable dt = DataAccess.selectData(query_select);
SqlDataReader dr = DataAccess.selectDataReader(query_select);
while (dr.Read())
{
string dpt_name = dr.GetString(1);
int dpt_id = (int)dr.GetValue(0);
comboBox1.DataSource = dt;
comboBox1.ValueMember = dpt_id; // error here
comboBox1.DisplayMember = dpt_name;
}
}
You must assign name of column in DataSource (DataTable) to ValueMenmber and DisplayMember as string, and you don't need to use while loop, like this :
void Fillcombo()
{
string query_select = "SELECT * FROM department";
DataTable dt = DataAccess.selectData(query_select);
comboBox1.DataSource = dt;
comboBox1.ValueMember = "ColumnName_DepartmentID";
comboBox1.DisplayMember = "ColumnName_DepartmentName";
}
You should write it in a string format:
comboBox1.ValueMember = "dpt_id";

Binding search results to data grid

I want to add search functionality to my program. There's a class which has this function:
public DataTable Search()
{
string SQL = "Select * from Customer where " + mField + " like '%" + mValue + "%'";
DataTable dt = new DataTable();
dt = dm.GetData(SQL);
return (dt);
}
There are setter and getter properties for mField and mValue. DM is the object of class DataManagement, which has a method GetData:
public DataTable GetData(string SQL)
{
SqlCommand command = new SqlCommand();
SqlDataAdapter dbAdapter = new SqlDataAdapter();
DataTable DataTable = new DataTable();
command.Connection = clsConnection.GetConnection();
command.CommandText = SQL;
dbAdapter.SelectCommand = command;
dbAdapter.Fill(DataTable);
return (DataTable);
}
The search functionality is currently implemented like this:
private void btnfind_Click(object sender, EventArgs e)
{
//cust is the object of class customer//
if (tbCustName.Text != "")
{
cust.Field="CustName";
cust.Value = tbCustName.Text;
}
else if (tbAddress.Text != "")
{
cust.Value = tbAddress.Text;
cust.Field="Address";
}
else if (tbEmail.Text != "")
{
cust.Value = tbEmail.Text;
cust.Field="Email";
}
else if (tbCell.Text != "")
{
cust.Value = tbCell.Text;
cust.Field = "Cell";
}
DataTable dt = new DataTable();
dt = cust.Search();
dgCustomer.DataSource = dt;
RefreshGrid();
}
private void RefreshGrid()
{
DataTable dt = new DataTable();
dt = cust.GetCustomers();
dgCustomer.DataSource = dt;
}
This is not working. I don't know why. Please help.
Add a DataBind() statement in your RefreshGrid() method to have your new results actually shown on the Grid.
private void RefreshGrid()
{
DataTable dt = cust.GetCustomers();
dgCustomer.DataSource = dt;
dgCustomer.DataBind();
}
Consider modifying your other method as well:
Your ad-hoc SQL has a SQL injection vulnerability. Stop everything until you fix that!
btnfind_Click doesn't need to end up calling cust.Search() twice.
private void btnfind_Click(object sender, EventArgs e)
{
//<snip>
// no need to do all this twice.
// DataTable dt = new DataTable();
// dt = cust.Search();
// dgCustomer.DataSource = dt;
RefreshGrid();
}
Your RefreshGrid method is overwriting the DataSource you set in btnfind_Click... don't call it, just call DataBind
private void btnfind_Click(object sender, EventArgs e)
{
...
DataTable dt = cust.Search();
dgCustomer.DataSource = dt;
dgCustomer.DataBind();
}
By the way, you don't need to assign a new DataTable to dt if you're immediately setting it to the result of cust.Search... you're just creating an instance for nothing (I fixed it in the code above)

Categories

Resources