Parameter act the same as regular string - c#

When I type ' in my TextBox, it's resulting an error. I know that because the ' is part of SQL Query. How do I avoid that? I've done it with Parameter, but didn't even work.
private void theFilter(string FilterValue) {
string thisQuery = "SELECT * FROM [Customer] WHERE CONCAT([Name], [Address], [Discount]) LIKE '%" + #FilterValue + "%'";
using(SqlConnection thisSqlConnection = new SqlConnection(theConnectionString))
using(SqlCommand thisSqlCommand = new SqlCommand(thisQuery, thisSqlConnection)) {
thisSqlCommand.Parameters.AddWithValue("#FilterValue", FilterValue);
using(SqlDataAdapter thisSqlDataAdapter = new SqlDataAdapter(thisSqlCommand))
using(DataTable thisDataTable = new DataTable()) {
thisSqlDataAdapter.Fill(thisDataTable);
DataGrid_Customer.ItemsSource = thisDataTable.DefaultView;
}
}
}

Try using this one
private void theFilter(string FilterValue) {
string thisQuery = "SELECT * FROM [Customer] WHERE CONCAT([Name], [Address], [Discount]) LIKE #FilterValue";
using(SqlConnection thisSqlConnection = new SqlConnection(theConnectionString))
using(SqlCommand thisSqlCommand = new SqlCommand(thisQuery, thisSqlConnection)) {
thisSqlCommand.Parameters.AddWithValue("#FilterValue", "%" + FilterValue + "%");
using(SqlDataAdapter thisSqlDataAdapter = new SqlDataAdapter(thisSqlCommand))
using(DataTable thisDataTable = new DataTable()) {
thisSqlDataAdapter.Fill(thisDataTable);
DataGrid_Customer.ItemsSource = thisDataTable.DefaultView;
}
}
}
Remember that you are using strings in parameters, not variables. You have to indicate the '%' in the AddWithValue method to be able to use wildcards in your query.

private void theFilter(string FilterValue) {
string thisQuery = "SELECT * FROM [Customer] WHERE CONCAT([Name], [Address], [Discount]) LIKE #FilterValue";
using(SqlConnection thisSqlConnection = new SqlConnection(theConnectionString))
using(SqlCommand thisSqlCommand = new SqlCommand(thisQuery, thisSqlConnection)) {
thisSqlCommand.Parameters.AddWithValue("#FilterValue", "%" + SqlLikeEscape(FilterValue) + "%");
using(SqlDataAdapter thisSqlDataAdapter = new SqlDataAdapter(thisSqlCommand))
using(DataTable thisDataTable = new DataTable()) {
thisSqlDataAdapter.Fill(thisDataTable);
DataGrid_Customer.ItemsSource = thisDataTable.DefaultView;
}
}
}
// This function is important, since otherwise if there is a % in the table (or other special LIKE characters) then it is hard to search for them
//see https://stackoverflow.com/questions/18693349/how-do-i-find-with-the-like-operator-in-sql-server
public static string SqlLikeEscape(string value)
{
if (string.IsNullOrEmpty(value)) return value;
return Regex.Replace(value, #"(?<ch>%|_|\[)", #"[${ch}]");
}

Related

how to write a single sql query based on combobox selection?

I have a winform in which user input values through a combobox. I am assigning combobox value to search db. If there is no selection then the SQL server query should not use that column to filter.
example -
if (string.IsNullOrEmpty(combobox1.text)) {
.....Select * from country
}
else if (combobox1.selectedindex > -1) {
....Select * from country where city_name = combobox.text
}
Is there a way to write a single query instead of using this multiple 'IF' conditions in case where user selects or doesn't select a value from combobox.
It is important to parameterize as well:
private const string _select = "select * from country";
void DoSomething()
{
string sql = string.Empty;
if (combobox1.SelectedIndex > -1)
{
command.Parameters.AddWithValue("#1", (string)combobox1.SelectedValue);
sql = " where city_name = #1";
}
sql = _select + sql;
command.CommandText = sql;
command.Execute...
}
#un-lucky asked me how would I deal with many conditions - here is one way
var conditions = new List<string>();
if (/* condition 1*/)
{
command.Parameters.AddWithValue("#2", (string)cboN.SelectedItem);
conditions.Add("col1 = #2");
}
if (/* condition 2*/)
{
command.Parameters.AddWithValue("#3", textBoxN.Text);
conditions.Add("col2 = #3");
}
if (conditions.Count > 0)
sql = _select + " where " + string.Join(" AND ", conditions.ToArray());
You can use the shorthand if only if you have two conditions:
string query = string.Format("Select * from country{0}", string.IsNullOrEmpty(combobox1.text) ? "" : " where city_name = " + combobox1.text);
Hope it helps!
I think you have to try something like this with parameterization:
StringBuilder queryBuilder = new StringBuilder("Select * from country Where 1=1 ");
SqlCommand cmdSql = new SqlCommand();
if (combobox1.selectedindex > -1)
{
queryBuilder.Append(" And city_name = #city_name ");
cmdSql.Parameters.Add("#city_name", SqlDbType.VarChar).Value = combobox.text;
}
else if(Condition 2)
{
queryBuilder.Append(" And column2 = #col2 ");
cmdSql.Parameters.Add("#col2", SqlDbType.VarChar).Value = "some Value here;
}
// Build the query like this
cmdSql.CommandText= = queryBuilder.ToString();
cmdSql.Connection = conObject;
// Here you can execute the command
I have a sample, try it
string select = this.combobox1.GetItemText(this.combobox1.SelectedItem); cm1 = new SqlCommand("Select * from country where city_name=#select or #select is null", con);
cm1.Parameters.Add("#select", SqlDbType.NVarChar, 50);
cm1.Parameters["#select"].Value = select;
dap = new SqlDataAdapter(cm1);
ds = new System.Data.DataSet();
dap.Fill(ds, "DATABASE");
//DataGridView1.DataSource = ds.Tables[0]; get data

SQL query return List

I can't seem to get this working:
My table column headers are 'genre' 'artist' 'album'
and the params I'm passing in are (type, filter, value) ("artist", "genre", "Rock") where there are two rows in the db with "Rock" for the genre.
When I follow the debugger, the 'while (reader.Read())' must return false because the loop is never entered and thus nothing written to the List.
public static List<String> getWithFilter(String type, String filter, String value)
{
List<String> columnData = new List<String>();
string query = "SELECT #type FROM Music WHERE" +
" #filter = '#value'";
SqlConnection connection = Database.GetConnection();
SqlCommand getData = new SqlCommand(query, connection);
getData.Parameters.AddWithValue("#type", type);
getData.Parameters.AddWithValue("#filter", filter);
getData.Parameters.AddWithValue("#value", value);
connection.Open();
using (connection)
{
using (getData)
{
using (SqlDataReader reader = getData.ExecuteReader())
{
while (reader.Read())
{
columnData.Add(reader.GetString(0));
}
}
}
}
return columnData;
}
You cannot use parameters for the names of columns and you don't put quotes around them when using them. Right now your query is the equivalent of
SELECT 'artist' FROM Music WHERE 'genre' = '#value'
You can do the following instead.
string query = "SELECT " + type + " FROM Music WHERE " + filter + " = #value";
And just remove the lines that create the #type and #fitler parameters.
You're looking either for formatting or string interpolation (requires C# 6.0):
string query =
$#"SELECT {type}
FROM Music
WHERE {filter} = #value";
...
getData.Parameters.AddWithValue("#value", value);
Formatting is a bit more wordy:
string query = String.Format(
#"SELECT {0}
FROM Music
WHERE {1} = #value", type, filter);
I assuming that you're using .net 2
DateTime current = DateTime.Now;
Console.WriteLine(current);
SqlConnection conn = new SqlConnection();
string q = "SELECT #field FROM student";
SqlDataAdapter da = new SqlDataAdapter(q, conn);
da.SelectCommand.Parameters.AddWithValue("#field", "snName");
DataTable dt = new System.Data.DataTable();
conn.Open();
da.Fill(dt);
conn.Close();
List<string> names = new List<string>();
foreach (DataRow dr in dt.Rows)
{
names.Add(dr[0].ToString());
}
Console.WriteLine("Fetching {0} data for {1}", names.Count, DateTime.Now - current);
Console.ReadKey();
You can use lambda expression to mapping the datatable in .net >4

Writing a SQL statement based on the values selected in a checkboxlist

I have two checkbox lists, one for a division and one for a course. One division can have many courses so what I want to do is have my user select whichever divisions they want as there are only 10 then display the courses in another checkbox list which are offered by the divisions that have been selected.
Precursor info:
private DataTable GetData(string query)
{
string constr = ConfigurationManager.ConnectionStrings["DatabaseName"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = query;
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataSet ds = new DataSet())
{
DataTable dt = new DataTable();
sda.Fill(dt);
return dt;
}
}
}
}
}
This is my code where I bind the data to the Divisions checkbox list:
protected void GetDiv()
{
string query = " Select distinct uio.OFFERING_ORGANISATION as [Div], ou.FES_FULL_NAME as [Division] From UNIT_INSTANCE_OCCURRENCES uio " +
" inner join ORGANISATION_UNITS ou on uio.OFFERING_ORGANISATION = ou.ORGANISATION_CODE " +
" inner join REPORTYEARS ry on uio.CALOCC_OCCURRENCE_CODE = ry.CAL_OCC " +
" Where ry.REPORT_YEAR = (select DETAILS from EF_REFERENCE_DATA Where REC_TYPE = 'Rep_Year') and uio.OFFERING_ORGANISATION is not null Order By [Division] ";
cbDivSelect.DataSource = GetData(query);
cbDivSelect.DataTextField = "DIVISION";
cbDivSelect.DataValueField = "DIV";
cbDivSelect.DataBind();
}
I use this to get a list of the divisions selected:
protected void cbDivSelect_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (ListItem item in cbDivSelect.Items)
{
if (item.Selected) Divisions.Add(item);
}
}
and then this to display the Courses:
protected void GetCourse()
{
foreach(ListItem item in Divisions)
{
string GetCourses = "SELECT distinct Course_Code,Course_Code + ' - ' + Marketing_Title AS COURSE, Parent FROM e_prospectus WHERE (Div = '" + item.Value.ToString() + "') ORDER BY Course_Code";
cbCourseSelect.DataSource = GetData(GetCourses);
cbCourseSelect.DataTextField = "COURSE";
cbCourseSelect.DataValueField = "Course_Code";
cbCourseSelect.DataBind();
}
}
Now currently it only displays the lowest course in the list which has been selected, i'm assuming because i keep changing the data source and it doesn't accumulate but is there any way i can change my code to accommodate what i want? thanks
Create one DataTable as DataSource and Merge() the results of GetData() into it.
This would build the whole set in memory. Depending how many Courses you expect using FakeisMe approach of building one query to get all courses out of the database at once might be a lot faster.
string divisions = string.empty ;
foreach(ListItem item in Divisions)
{
divisions = divisions + item.Value.tostring() + ",";
}
if (divisions != string.empty)
{
divisions = divisions.Remove(divisions.Length -1, 1)
string GetCourses = "SELECT distinct Course_Code,Course_Code + ' - ' + Marketing_Title AS COURSE, Parent FROM e_prospectus
WHERE (Div in (" + divisions + ")) ORDER BY Course_Code";
cbCourseSelect.DataSource = GetData(GetCourses);
cbCourseSelect.DataTextField = "COURSE";
cbCourseSelect.DataValueField = "Course_Code";
cbCourseSelect.DataBind();
}

c# fill dataTable

I have a textbox window1.xaml that works as a searchbox. I am using a integrated sql database in my project and I have a dataset.xsd as well with tabel adapters and queries.
Whenever I need to query the database I do something like this:
BooksTableAdapter tableAdapterBooks = new BooksTableAdapter();
dataSetLibrary.BooksDataTable dataTableBooks;
dataTableBooks = tableAdapterBooks.getDataByTitle(searchText);
For this searchbox I have the following code.
string[] allWords = txtSearch.Text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
string sql = "SELECT Books.ISBN, Books.Title, Books.Tag, Books.Image, Books.photoType, Publishers.Name AS publisherName FROM Books INNER JOIN Publishers ON Books.codPublisher = Publishers.codPublisher WHERE ";
using (SqlCommand command = new SqlCommand())
{
for (int i = 0; i < allWords.Length; ++i)
{
if (i > 0)
sql += "OR ";
string paramName = "#param" + i.ToString();
sql += string.Format("(Books.Title LIKE {0}) ", paramName);
command.Parameters.AddWithValue(paramName, allWords[i] + "%");
}
command.CommandText = sql;
}
How can I use the command to query my database and fill dataTableBooks?
After hours around this, I have come up with this solution.
private SqlConnection sqlConn = new SqlConnection();
private System.Data.DataSet dataSet = new System.Data.DataSet();
private System.Data.DataTable dataTable;
private System.Data.DataRow dataRow;
private SqlCommand search(string searchParam, int searchOption)
{
SqlCommand command = new SqlCommand();
string sql;
string[] allWords = searchParam.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (searchOption == 1)
{
sql = "SELECT Livros.ISBN, Livros.Titulo, Livros.Tema, Livros.Resumo, Livros.Imagem, Livros.fotoTipo, Editoras.Nome AS nomeEditora FROM Livros INNER JOIN Editoras ON Livros.codEditora = Editoras.codEditora WHERE ";
}
else
{
sql = "SELECT Livros.ISBN, Livros.Titulo, Livros.Tema, Livros.Resumo, Livros.Imagem, Livros.fotoTipo, Editoras.Nome AS nomeEditora FROM Livros INNER JOIN livrosAutores ON Livros.ISBN = livrosAutores.ISBN INNER JOIN Autores ON livrosAutores.idAutor = Autores.idAutor INNER JOIN Editoras ON Livros.codEditora = Editoras.codEditora WHERE ";
}
using (command)
{
for (int i = 0; i < allWords.Length; ++i)
{
if (i > 0)
{
sql += "OR ";
}
if (searchOption == 1)
{
sql += string.Format("(Livros.Titulo LIKE '%{0}%') ", allWords[i]);
}
else
{
sql += string.Format("(Livros.Autor LIKE '%{0}%') ", allWords[i]);
}
}
command.CommandText = sql;
}
return command;
}
protected void Bind()
{
sqlConn.ConnectionString = Properties.Settings.Default.BibliotecaConnectionString;
string connectionString = sqlConn.ConnectionString.ToString();
SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(search(searchText, searchOption).CommandText, connectionString);
sqlDataAdapter.Fill(dataSet, "livrosTitulo");
dataTable = dataSet.Tables["livrosTitulo"];
dataGrid.DataContext = dataTable.DefaultView;
}

SQL Syntax Error (INSERT command)

I have a form with a text box and button, such that when the user clicks the button, the specified name in the text box is added to a table in my sql database. The code for the button is as follows:
private void btnAddDiaryItem_Click(object sender, EventArgs e)
{
try
{
string strNewDiaryItem = txtAddDiaryItem.Text;
if (strNewDiaryItem.Length == 0)
{
MessageBox.Show("You have not specified the name of a new Diary Item");
return;
}
string sqlText = "INSERT INTO tblDiaryTypes (DiaryType) VALUES = ('" + strNewDiaryItem + "');";
cSqlQuery cS = new cSqlQuery(sqlText, "non query");
PopulateInitialDiaryItems();
MessageBox.Show("New Diary Item added succesfully");
}
catch (Exception ex)
{
MessageBox.Show("Unhandled Error: " + ex.Message);
}
}
The class cSqlQuery is a simple class that executes various T-SQL actions for me and its code is as follows:
class cSqlQuery
{
public string cSqlStat;
public DataTable cQueryResults;
public int cScalarResult;
public cSqlQuery()
{
this.cSqlStat = "empty";
}
public cSqlQuery(string paramSqlStat, string paramMode)
{
this.cSqlStat = paramSqlStat;
string strConnection = BuildConnectionString();
SqlConnection linkToDB = new SqlConnection(strConnection);
if (paramMode == "non query")
{
linkToDB.Open();
SqlCommand sqlCom = new SqlCommand(paramSqlStat, linkToDB);
sqlCom.ExecuteNonQuery();
linkToDB.Close();
}
if (paramMode == "table")
{
using (linkToDB)
using (var adapter = new SqlDataAdapter(cSqlStat, linkToDB))
{
DataTable table = new DataTable();
adapter.Fill(table);
this.cQueryResults = table;
}
}
if (paramMode == "scalar")
{
linkToDB.Open();
SqlCommand sqlCom = new SqlCommand(paramSqlStat, linkToDB);
this.cScalarResult = (Int32)sqlCom.ExecuteScalar();
linkToDB.Close();
}
}
public cSqlQuery(SqlCommand paramSqlCom, string paramMode)
{
string strConnection = BuildConnectionString();
SqlConnection linkToDB = new SqlConnection(strConnection);
paramSqlCom.Connection = linkToDB;
if (paramMode == "table")
{
using (linkToDB)
using (var adapter = new SqlDataAdapter(paramSqlCom))
{
DataTable table = new DataTable();
adapter.Fill(table);
this.cQueryResults = table;
}
}
if (paramMode == "scalar")
{
linkToDB.Open();
paramSqlCom.Connection = linkToDB;
this.cScalarResult = (Int32)paramSqlCom.ExecuteScalar();
linkToDB.Close();
}
}
public string BuildConnectionString()
{
cConnectionString cCS = new cConnectionString();
return cCS.strConnect;
}
}
The class works well throughout my application so I don't think the error is in the class, but then I can't be sure.
When I click the button I get the following error message:
Incorrect syntax near =
Which is really annoying me, because when I run the exact same command in SQL Management Studio it works fine.
I'm sure I'm missing something rather simple, but after reading my code through many times, I'm struggling to see where I have gone wrong.
you have to remove = after values.
string sqlText = "INSERT INTO tblDiaryTypes (DiaryType) VALUES ('" + strNewDiaryItem + "');"
and try to use Parameterized queries to avoid Sql injection. use your code like this. Sql Parameters
string sqlText = "INSERT INTO tblDiaryTypes (DiaryType) VALUES (#DairyItem);"
YourCOmmandObj.Parameters.AddwithValue("#DairyItem",strNewDiaryIItem)
Remove the = after VALUES.
You do not need the =
A valid insert would look like
INSERT INTO table_name (column1, column2, column3,...)
VALUES (value1, value2, value3,...)
Source: http://www.w3schools.com/sql/sql_insert.asp
Please use following:
insert into <table name> Values (value);
Remove "=", and also i would recommend you to use string.format() instead of string concatenation.
sqlText = string.format(INSERT INTO tblDiaryTypes (DiaryType) VALUES ('{0}'), strNewDiaryItem);"

Categories