if (allStatusCheckBox.Checked != true)
{
if (assComboBox.SelectedIndex != -1 && revComboBox.SelectedIndex != -1)
{
dataSda = new SqlDataAdapter("SELECT DATAACTUALID WHERE ASSIGNEDSTATUS LIKE '" + statusComboBox.SelectedValue + "' AND A_ASSIGNEDTO.EMP_ID LIKE '" + assComboBox.SelectedValue + "%' AND A_TOBEREVIEWEDBY.EMP_ID LIKE '" + revComboBox.SelectedValue + "%'", patientCon);
}
else if (assComboBox.SelectedIndex != -1 && revComboBox.SelectedIndex == -1)
{
dataSda = new SqlDataAdapter("SELECT DATAACTUALID WHERE ASSIGNEDSTATUS LIKE '" + statusComboBox.SelectedValue + "' AND A_ASSIGNEDTO.EMP_ID LIKE '" + assComboBox.SelectedValue + "%'", patientCon);
}
else if (assComboBox.SelectedIndex == -1 && revComboBox.SelectedIndex != -1)
{
dataSda = new SqlDataAdapter("SELECT DATAACTUALID WHERE ASSIGNEDSTATUS LIKE '" + statusComboBox.SelectedValue + "' AND A_TOBEREVIEWEDBY.EMP_ID LIKE '" + revComboBox.SelectedValue + "%'", patientCon);
}
else
{
dataSda = new SqlDataAdapter("SELECT DATAACTUALID WHERE ASSIGNEDSTATUS LIKE '" + statusComboBox.SelectedValue + "'", patientCon);
}
}
else
{
//REPEAT WITHOUT STATUSCOMBOX.SELECTED VALUE
}
Basically the point of this code is to display some information based on whether certain filters have been applied. However with my current approach every time I apply a new filter my number of if statements is growing exponentially. I am worried my code will soon become slow and hard to manage as I apply more filters. Is there a better way of achieving the same results?
You have quite a few bigger problems to worry about with your code before worrying about some if statements. I will address all of those and you will start to see that fixing them, will fix your mess.
First, your SQL query text is basically the same across all of your queries:
SELECT
DATAACTUALID,
A_DATAACTUAL.TRIGGERPOINTSID,
TBLPT.PT_ID,
NAME as C,
A_ASSIGNEDTO.EMP_ID as ASSIGNEDID,
A_TOBEREVIEWEDBY.EMP_ID as REVIEWERID,
TBLPT.LASTNAME + ' ' + TBLPT.FIRSTNAME as Patient,
TRIGGERNAME as DESCRIPTION,
TRIGGERPOINTNAME as DETAIL,
A_ASSIGNEDTO.EMP_LASTNAME + ' ' + A_ASSIGNEDTO.EMP_FIRSTNAME as Assigned,
TODOBY, A_TOBEREVIEWEDBY.EMP_LASTNAME + ' ' + A_TOBEREVIEWEDBY.EMP_FIRSTNAME as Reviewer,
REVIEWDATE,
GRADE,
COMMENT
FROM A_DATAACTUAL
INNER JOIN TBLPT ON A_DATAACTUAL.PT_ID = TBLPT.PT_ID
INNER JOIN A_TRIGGERPOINTS ON A_DATAACTUAL.TRIGGERPOINTSID = A_TRIGGERPOINTS.TRIGGERPOINTSID
INNER JOIN A_TRIGGERS ON A_TRIGGERPOINTS.TRIGGERID = A_TRIGGERS.TRIGGERID
INNER JOIN A_ASSIGNEDTO ON A_DATAACTUAL.ASSIGNEDTO = A_ASSIGNEDTO.EMP_ID
INNER JOIN A_TOBEREVIEWEDBY ON A_DATAACTUAL.TOBEREVIEWEDBY = A_TOBEREVIEWEDBY.EMP_ID
INNER JOIN A_STATUS ON A_DATAACTUAL.ASSIGNEDSTATUS = A_STATUS.STATUSID
You see all those joins and specific selects/aliases? This is a prime opportunity to create a SQL View, then you can query that newly created View instead of constantly doing the same exact query over and over again.
Lets say you named the view v_SomeView, all your queries would look like this:
"SELECT * FROM v_SomeView WHERE A_ASSIGNEDTO.EMP_ID LIKE ..."
"SELECT * FROM v_SomeView WHERE A_TOBEREVIEWEDBY.EMP_ID LIKE ..."
Use the power of SQL, C# should only be responsible for so much...
Second huge problem is you have SQL Injection vulnerabilities. You should never concatenate SQL queries like this. Always use parameters.
A quick example if you must use SqlDataAdapter:
dataSda = new SqlDataAdapter("SELECT * FROM v_SomeView WHERE ASSIGNEDSTATUS = #someValue", patientCon);
dataSda.SelectCommand.Parameters.Add(new SqlParameter("#someValue", assComboBox.SelectedValue));
With these two changes you have made your code more secure, you have kept it DRY and you leveraged the power of SQL.
Related
I am using WinForms and I want to use SQL if statement in my code.
Here is a small example. I am using SQL long query and I want to use IF statement to do two different functions. Here is example.
string query =
"SELECT U1.UserID,
U1.FirstName,
U1.LastName,
C1.UserID,
C1.FriendID
FROM USERS U1
INNER JOIN Chat C1 ON U1.UserID = C1.UserID
WHERE C1.UserID = '" + MyName.Uid + "'
AND C1.FriendID = '" + friendid + "'
OR C1.UserID = '" + friendid + "'
AND C1.FriendID = '" + MyName.Uid + "'
ORDER BY C1.ChatID";
There is some more stuff in there. But here is what I need. I know this gonna be wrong, I need someone to help me to write correct if statement.
if (C1.UserID = '" + MyName.Uid + "' and C1.FriendID = '" + friendid + "') {
// some code.
}
You cannot use use SQL Query this way.
First you have to execute your query to get data from database. Once you have it, you can do your if statement to get what you wanted.
And for your if statement you should use Equals to test strings equality.
if (C1.UserID.Equals(someString) && C1.FriendID.Equals(anotherString))
{
//some code.
}
I am creating a Windows Forms application and now at certain point I need to make a database connection, I have inserted the values to database easily, but now its not updating my data, I am using following query for this purpose:
MySqlCommand sda = new MySqlCommand(#"Update shedulling.tablelayout1 set date = '"
+ date + "',line = " + line + ",col1 = '" + first_textbox.text + "', col2 = '"
+ sec_textbox.text + "',col3_textbox.text = '" + thi_textbox.text
+ "',col4_textbox.text = '" + four + "' where date = '" + date + "' AND line = '"
+ line.ToString() + "' ", conn);
conn is a connection string which is written fine, and date and line are string and integer values send as an argument to this function.
You have missed single quotes in line part. Change it like this line = '" + line + "'.
Also there is one more notable thing in your code: you are trying to find the record in the table that is not exist yet in where clause where date = '" + date + "' AND line = '" + line.ToString() + "' note in this line date and line are the new values not old values so no rows affected in the update query. You should use old values of date and line in the where clause.
Also you should always use parameterized queries. This kind of string concatenations are open for SQL Injection.
Try debugging the code, there must be INSERT statement executing somewhere in your code.
UPDATE: If "line" is integer variable then you need to convert it into string. You have converted it after WHERE clause but not after SET clause.
You may want to post some more code to get exact answer.
I use mysql as database where I store my data.
I have a windows form with textboxes radiobuttons, comboboxes and more; where people give personal information about themselves like (first name, last name, sex, date birthday, phone, father name and more like this). (40 fields total)
I want to do a search button. With this button I want to fill some fields and after I push the search button a new window be opened containing all people with same personal information. I achieved to do a search button for one field (for example searching only by name).
But I have a problem when I select to search with more than one fields. For example I select to search all people who have name:Chris, Nickname:Dung, sex:Male, Birth_Country:UK and other but when I push search it gives back a window with irrelevant with the search data. Can someone help me with that?
The code I made for the search button after changes is:
public MySqlDataAdapter da;
public DataSet ds;
public string sTable = "data";
private void anazitisi_button_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
try
{
conn = openconnectio.GetConn();
string radiob = null;
if (radioButton1.Checked == true)
{
radiob = radioButton1.Text;
}
else if(radioButton2.Checked == true)
{
radiob = radioButton2.Text;
}
StringBuilder Query = new StringBuilder("SELECT * FROM data d INNER JOIN country c ON d.id_data = c.id_country WHERE 1=1 ");
if (!String.IsNullOrEmpty(textBox1.Text))
Query.Append(" AND name like '" + textBox1.Text + "'");
if (!String.IsNullOrEmpty(textBox2.Text))
Query.Append(" AND lastname like '" + textBox2.Text + "'");
if (!String.IsNullOrEmpty(radiob))
Query.Append(" AND sex like '" + radiob + "'");
if (!String.IsNullOrEmpty(maskedTextBox1.Text))
Query.Append(" AND birthdate like '" + maskedTextBox1.Text + "'");
if (!String.IsNullOrEmpty(maskedTextBox2.Text))
Query.Append(" AND phone_number like '" + maskedTextBox2.Text + "'");
MySqlDataAdapter da = new MySqlDataAdapter(Query.ToString(), conn);
ds = new DataSet();
da.Fill(ds, sTable);
conn.Close();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
DataGridView dg1 = new DataGridView();
form2.Controls.Add(dg1);
dg1.Dock = DockStyle.Fill;
dg1.Refresh();
dg1.DataSource = ds;
dg1.DataMember = sTable;
form2.Show();
if (conn != null)
{
conn.Close();
}
}
}
My results after search is fine when i comment that code:
(birthdate code) and i dont used as search of course.
//if (!String.IsNullOrEmpty(maskedTextBox1.Text))
// Query.Append(" AND birthdate like '" + maskedTextBox1.Text + "'");
But when i use the (birthdate code) i get us result only a blank row.
I think because the birthdate maskedTextbox have a mask: 00/00/0000
Any suggestion?
Thanks.
I think you should consider three things
1- You may replace OR with And in your query
I mean instead of using
da = new MySqlDataAdapter(
"SELECT * FROM data INNER JOIN country ON id_data = id_country
WHERE name like '" + textBox1.Text +
"'OR lastname like '" + textBox2.Text +
"'OR sex like '" + radiob +
"'OR birthdate like '" + maskedTextBox1.Text +
"'OR phone
_number like '" + maskedTextBox2.Text + "' ;", conn);
You may use
da = new MySqlDataAdapter(
"SELECT * FROM data INNER JOIN country ON id_data = id_country
WHERE name like '" + textBox1.Text +
"'AND lastname like '" + textBox2.Text +
"'AND sex like '" + radiob +
"'AND birthdate like '" + maskedTextBox1.Text +
"'AND phone_number like '" + maskedTextBox2.Text + "' ;", conn);
2- You have to build your query string based on your text boxes and else seeing if they have any value, something like this:
StringBuilder Query = "SELECT * FROM data INNER JOIN country ON id_data = id_country
WHERE 1=1 ";
if(!String.IsNullOrEmpty(textBox1.Text))
Query.Append(" AND name like '" + textBox1.Text);
....
3- Sql Injection vulnerabilities
oh my God !!! Some programming !!!
where clause must created by and/or ,... other clauses ,
so ,
two solutions exist :
On server Side by Store Procedure by below definition :
you must care by position of AND/OR in below :
CREATE PROCEDURE [dbo].[dbo_Bank_SELByFields]
(
#ID nvarchar(50) = NULL ,
#BankName nvarchar(50) = NULL ,
#BankCode nvarchar(50) = NULL ,
#Address nvarchar(50) = NULL ,
#BranchCode nvarchar(50) = NULL
)
AS
SELECT * FROM dbo.Bank WHERE
(
(#ID IS NULL OR ID = #ID) AND
(#BankName IS NULL OR BankName =#BankName) AND
(#BankCode IS NULL OR BankCode =#BankCode) AND
(#Address IS NULL OR Address =#Address) AND
(#BranchCode IS NULL OR BranchCode =#BranchCode)
) ORDER BY BankCode
//---you know call the Sp . OK?
and other solution in your business layer code :
if you use ORM such as Entity Framework , very easy By IQueryable object, you can use below :
var selectByEnyCondition=(from c in ctx.customer ...);
//---- you must add by below way :
if(!(String.IsNullOrEmpty(txtName.Text)))
{
selectByEnyCondition.Where(.....);
}
if(!String.IsNullOrEmpty(sex))
{
selectByEnyCondition= opportunites.Where(.....);
}
//------
/* **** beacuse you use by ADO.NET technique you should use StringBuilder -->*/
StringBuilder query;
query.add("SELECT * FROM BankTbl WHERE ");
if(!(String.IsNullOrEmpty(txtName.Text))){
query.Add("Name Like {0}",txtName.Text);
//-----now continue for build your criteria
king reguard
bye.....
The following is my MS sql-server statement, which is used in my C# Windows application. As the title suggests, it selects all product numbers that are between the Textbox dates. I'm fairly inexperienced with SQL, so my attempt may be an atrocity. SQL seems to think so.
string strSQL = "SELECT * FROM HISTORY ORDER BY productNumber WHERE (#strt_date >= '" + Convert.ToDateTime(KHDate1Box.Text) + "' and #end_date <= '" + Convert.ToDateTime(KHDate2Box.Text) + "')";
SQL error message: "Incorrect syntax near the keyword 'WHERE'."
string strSQL = "SELECT * FROM HISTORY ORDER BY productNumber WHERE (#strt_date >= '" + Convert.ToDateTime(KHDate1Box.Text) + "' and #end_date <= '" + Convert.ToDateTime(KHDate2Box.Text) + "')";
That's because the WHERE clause should come before ORDER BY
string strSQL = "SELECT * FROM HISTORY WHERE (#strt_date >= '" + Convert.ToDateTime(KHDate1Box.Text) + "' and #end_date <= '" + Convert.ToDateTime(KHDate2Box.Text) + "' ORDER BY productNumber)" ;
" SELECT * FROM HISTORY
WHERE (#strt_date >= '" + Convert.ToDateTime(KHDate1Box.Text) + "' and #end_date <= '" + Convert.ToDateTime(KHDate2Box.Text) + "')
ORDER BY productNumber "
the order by goes after the where clause
If it's only dates, there's not much chance of SQL injection especially if you validate it.
If you must pass a date as string to SQL Server, it should be in the unambiguous YYYYMMDD format. But I'd also add the validation of the input as date.
Have this before that statement
CultureInfo provider = CultureInfo.InvariantCulture;
Then, change it to
string strSQL = "SELECT * FROM HISTORY ORDER BY productNumber WHERE (#strt_date >= '" +
DateTime.ParseExact(KHDate1Box.Text, "d", provider).ToString("yyyyMMdd")
+ "' and #end_date <= '" +
DateTime.ParseExact(KHDate2Box.Text, "d", provider).ToString("yyyyMMdd") + "')";
Catch errors from failing to parse the date.
Reference: I used "d" but here's the list of Standard Datetime Formats
I have noticed that you are using #strt_date and #end_date (which are T-SQL variables) as column names. Also, the ORDER BY clause should be after the WHERE clause.
As an aside, there are a variety of reasons why you should not code a query in this way. Google "SQL Injection" for a very eye opening security issue.
Instead use parameterized queries. They are safer and less prone to syntax errors caused by invalid characters in the value fields.
http://www.csharp-station.com/Tutorial/AdoDotNet/lesson06
I am having problem with my asp.net app, in which I am dynamically building SQL query where I am using WHERE clause and adding OR depending on the fields which is entered. here is the scenario.
I have a Four TextBox, out of 2 is DateTime
i would like to search in the database if there is a value in any one text-box and return the results that is bind to a GridView. Now, if there is more than one text-box value then i need to add that as well and build OR in where clause. if there are no values in any one of the text-box then need to return all the results. BUT i am having problem in building the query as i have to go through the if else loop to see if there is any value or null. here is my code.
StringBuilder selectQuery = new StringBuilder();
disCode = SearchTextCouponCode.Text;
disName = SearchTextCouponName.Text;
if(StartDate.SelectedDate != null)
startDate = StartDate.SelectedDate.ToString("yyyy-MM-dd");
if(EndDate.SelectedDate != null)
endDate = EndDate.SelectedDate.ToString("yyyy-MM-dd");
// here is the main thing where i am getting the error
if (!string.IsNullOrEmpty(disCode))
{
selectQuery.Append("DISCOUNTCode = '" + disCode + "'");
}
if (!string.IsNullOrEmpty(disName))
{
selectQuery.Append(" OR DISCOUNTName = '" + disName + "'");
}
if (startDate != "0001-01-01")
{
selectQuery.Append(" OR StartDate = '" + startDate + "'");
}
if(endDate != "0001-01-01")
selectQuery.Append(" OR EndDate = '" + endDate + "'");
// I am using Object Data Source and the method i am passing is taking care of the SQL injection
DataSourceDis.SelectParameters["sqlCriteria"].DefaultValue = selectQuery.ToString();
GridDis.DataBind();
now, when i run the app, and leave the disCode text-box empty, then the query start with OR and gives me the error that incorrect syntax near where ..
please help.
/////////////////////////////////////////////////////////
i am calling another method after building up this query which is taking care of SQL Injection
/////////////////////////////////////////////////////////
The easiest thing you could do is change WHERE to:
WHERE 1=0
And then ensure all of your WHERE conditions start with OR
As Richard has pointed out however, this is not best practice, and you would be better using a stored procedure or LINQ. Using stored procedures you could pass all these parameters to the procedure and then do something like:
AND (#disName IS NULL OR DiscountName=#disName)
You could set all lines to have " OR " at the end (instead of the start), such as...
selectQuery.Append("DISCOUNTCode = '" + disCode + "' OR ");
And then before using the .ToString() have...
if(selectQuery.Length > 0)
{
selectQuery.Length -= 4;
}
If you use the WHERE 1=0 OR solution, you may get performance impacts.
I'd recommend creating a variable to mark the conjunction and changing it when you add a condition
string conjuction = " ";
if (!string.IsNullOrEmpty(disCode))
{
selectQuery.Append(conjunction);
selectQuery.Append("DISCOUNTCode = '" + disCode + "'");
conjuction = " OR ";
}
if (!string.IsNullOrEmpty(disName))
{
selectQuery.Append(conjunction);
selectQuery.Append("DISCOUNTName = '" + disName + "'");
conjuction = " OR ";
}
etc.
I don't know where your inputs are coming from, but be aware of the potential for a SQL injection attack in your current code.
I'd generally do it like this;
var conds = new List<string> ();
// here is the main thing where i am getting the error
if (!string.IsNullOrEmpty(disCode))
{
conds.Add("DISCOUNTCode = '" + disCode + "'");
}
if (!string.IsNullOrEmpty(disName))
{
conds.Add("DISCOUNTName = '" + disName + "'");
}
if (startDate != "0001-01-01")
{
conds.Add("StartDate = '" + startDate + "'");
}
if(endDate != "0001-01-01")
conds.Add("EndDate = '" + endDate + "'");
selectQuery.Append(String.Join(" OR ",conds));
It's a bit hideous building queries like this - better to use prepared statements or LINQ or your own query building class.
A valid Sql query e.g. SELECT * FROM EMPLOYEE WHERE Name = 'Hat' OR SURNAME = 'SOFT'
Looks like you case when the query starts with OR your StringBuilder Appends the query like this
SELECT * FROM EMPLOYEE WHERE OR SURNAME = 'SOFT' and its invalid becuase the OR KEYWORD directly after WHERE
when your disCode text-box is empty then Condition will be "OR DISCOUNTName" which is wrong you can not use "OR" after where
if (!string.IsNullOrEmpty(disCode))
{
selectQuery.Append("DISCOUNTCode = '" + disCode + "'");
}
if (!string.IsNullOrEmpty(disName))
{
selectQuery.Append(" OR DISCOUNTName = '" + disName + "'");
}