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;
}
Related
I am trying to execute this code in getting an error as
There is no row at position 2"
How can I solve this?
public JsonResult Question()
{
try
{
string [] Question=new string[2];
SqlConnection con = new SqlConnection(connectionString: "Server = (localdb)\\mssqllocaldb; Database = QuestionDb; Trusted_Connection = True; MultipleActiveResultSets = true");
con.Open();
string query = "";
query += #"select Id,Sum(Yes) AS T_Yes,Sum(No) AS T_No,Sum(DontKnow) AS T_DontKnow from dbo.Questions Group By Id";
SqlCommand cmd = new SqlCommand(query, con);
cmd.CommandText = query;
DataTable dt = new DataTable();
SqlDataAdapter cmd1 = new SqlDataAdapter(cmd);
cmd1.Fill(dt);
if (dt.Rows.Count == 0)
{
Question[0] = "0";
Question[1] = "0";
Question[2] = "0";
}
else
{
Question[0] = dt.Rows[0]["T_Yes"].ToString();
Question[1] = dt.Rows[1]["T_No"].ToString();
Question[2] = dt.Rows[2]["T_DontKnow"].ToString();
}
return Json(Question);
The problem is that you are mixing rows and columns. Use:
Question[0] = dt.Rows[0]["T_Yes"].ToString();
Question[1] = dt.Rows[0]["T_No"].ToString();
Question[2] = dt.Rows[0]["T_DontKnow"].ToString();
You must use always dt.Rows[0] (instead of [1] or [2]) to get the properties of the first row.
You're checking only to row count = 0, try this:
Also for comentary answer you need all data for the pie chart so need to recover all records.
Add a reference to System.Data, System.Collections.Generic and System.Linq to your project if this does not compile
List<string[]> listofIdGroups;
List<string[]> listofIdGroups;
listofIdGroups = dt.Rows.OfType<DataRow>()
.Select(dr => new string[3] { dr["T_Yes"].ToString(), dr["T_No"].ToString(), dr["T_DontKnow"].ToString() }).ToList();
you can read the list this way:
foreach (string[] question in listofIdGroups)
{
Console.WriteLine("Yes:" + question[0] + Environment.NewLine + "No: " + question[1] + Environment.NewLine + "DontKnow: " + question[2]);
}
try it here:
https://dotnetfiddle.net/0S1N3c
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}]");
}
I want to show data from data table on form_load using list box, and later update that data from list box on button click by Insert command. Function for that is fill_List(). This is my code:
OleDbConnection konekcija;
OleDbDataAdapter adapter = new OleDbDataAdapter();
DataTable dt = new DataTable();
public Form2()
{
InitializeComponent();
string putanja = Environment.CurrentDirectory;
string[] putanjaBaze = putanja.Split(new string[] { "bin" }, StringSplitOptions.None);
AppDomain.CurrentDomain.SetData("DataDirectory", putanjaBaze[0]);
konekcija = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=|DataDirectory|\B31Autoplac.accdb");
}
void fill_List()
{
konekcija.Open();
OleDbCommand komPrikaz = new OleDbCommand("SELECT * FROM GORIVO ORDER BY GorivoID ASC", konekcija);
adapter.SelectCommand = komPrikaz;
adapter.Fill(dt);
listBox1.Items.Clear();
for (int i = 0; i < dt.Rows.Count; i++)
{
string pom;
pom = dt.Rows[i][0].ToString() + " " + dt.Rows[i][1].ToString() + " " + dt.Rows[i][2];
listBox1.Items.Add(pom);
}
konekcija.Close();
}
private void Form2_Load(object sender, EventArgs e)
{
fill_List();
}
private void btnUpisi_Click(object sender, EventArgs e)
{
string s1, s2, s3;
s1 = tbSifra.Text;
s2 = tbNaziv.Text;
s3 = tbOpis.Text;
string Upisi = "INSERT INTO GORIVO (GorivoID, Naziv, Opis) VALUES (#GorivoID, #Naziv, #Opis)";
OleDbCommand komUpisi = new OleDbCommand(Upisi, konekcija);
komUpisi.Parameters.AddWithValue("#GorivoID", s1);
komUpisi.Parameters.AddWithValue("#Naziv", s2);
komUpisi.Parameters.AddWithValue("#Opis", s3);
string Provera = "SELECT COUNT (*) FROM GORIVO WHERE GorivoID=#GorivoID";
OleDbCommand komProvera = new OleDbCommand(Provera, konekcija);
komProvera.Parameters.AddWithValue("#GorivoID", s1);
try
{
konekcija.Open();
int br = (int)komProvera.ExecuteScalar();
if(br==0)
{
komUpisi.ExecuteNonQuery();
MessageBox.Show("Podaci su uspesno upisani u tabelu i bazu.", "Obavestenje");
tbSifra.Text = tbNaziv.Text = tbOpis.Text = "";
}
else
{
MessageBox.Show("U bazi postoji podatak sa ID = " + tbSifra.Text + ".", "Obavestenje");
}
}
catch (Exception ex1)
{
MessageBox.Show("Greska prilikom upisa podataka. " + ex1.ToString(), "Obavestenje");
}
finally
{
konekcija.Close();
fill_List();
}
}
Instead of this
It shows me this (added duplicates with new data)
Is there a problem in my function or somewhere else?
Another bug caused by global variables.
You are keeping a global variable for the DataTable filled by the fill_list method. This datatable is never reset to empty when you call fill_list, so at every call you add another set of rows to the datatable and then transfer this data inside the listbox. Use a local variable.
But the same rule should be applied also to the OleDbConnection and OleDbCommand. There is no need to keep global instances of them. Creating an object is really fast and the convenience to avoid global variables is better than the little nuisance to create an instance of the connection or the command.
void fill_List()
{
using(OleDbConnection konekcija = new OleDbConnection(......))
using(OleDbCommand komPrikaz = new OleDbCommand("SELECT * FROM GORIVO ORDER BY GorivoID ASC", konekcija))
{
DataTable dt = new DataTable();
konekcija.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(komPrikaz);
adapter.Fill(dt);
listBox1.Items.Clear();
for (int i = 0; i < dt.Rows.Count; i++)
{
string pom;
pom = dt.Rows[i][0].ToString() + " " + dt.Rows[i][1].ToString() + " " + dt.Rows[i][2];
listBox1.Items.Add(pom);
}
}
}
Clear your DataTable before filling it again.
void fill_List()
{
konekcija.Open();
OleDbCommand komPrikaz = new OleDbCommand("SELECT * FROM GORIVO ORDER BY GorivoID ASC", konekcija);
adapter.SelectCommand = komPrikaz;
dt.Clear(); // clear here
adapter.Fill(dt);
listBox1.Items.Clear();
for (int i = 0; i < dt.Rows.Count; i++)
{
string pom;
pom = dt.Rows[i][0].ToString() + " " + dt.Rows[i][1].ToString() + " " + dt.Rows[i][2];
listBox1.Items.Add(pom);
}
konekcija.Close();
}
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
Hey all I realise that this question has been asked before but even if I follow the answers I still cannot seem to get my code to work. The error occurs at "data_adapter.Fill(temp_table)" any help on what is going on would be appreciated.
string ConnStr = "Provider = Microsoft.Jet.OLEDB.4.0; Data Source = H:\\School Work\\Computing A Level\\Stock checker\\Program\\Morgan's Motors Database.mdb";
string Query = "SELECT * FROM [Car Info] WHERE #x ";
string FirstQuery = null;
int i = 0;
for (i = 0; i < ColumnName.Count - 1; i++)
{
FirstQuery += string.Format("{0} = {1} AND ", ColumnName[i], EnteredFields[i]);
}
FirstQuery += string.Format("{0} = {1}", ColumnName[i], EnteredFields[i]);
MessageBox.Show(Query);
OleDbConnection database_connection = new OleDbConnection(ConnStr);
OleDbCommand database_command = new OleDbCommand(Query, database_connection);
database_command.Parameters.AddWithValue("#x", FirstQuery);
OleDbDataAdapter database_adapter = new OleDbDataAdapter();
database_adapter.SelectCommand = new OleDbCommand(database_command.CommandText, database_connection);
DataTable temp_table = new DataTable();
database_adapter.Fill(temp_table);
BindingSource data_source = new BindingSource();
data_source.DataSource = temp_table;
dataGridView1.DataSource = data_source;
EDIT: I have made some progress in restructuring the code, now the problem is that the "?" isn't being replaced
string ConnStr = "Provider = Microsoft.ACE.OLEDB.12.0; Data Source = H:\School Work\Computing A Level\Stock checker\Program\Morgan's Motors Database.mdb;";
OleDbConnection conn_database = new OleDbConnection();
conn_database.ConnectionString = ConnStr;
OleDbCommand comm_database = new OleDbCommand();
comm_database.CommandText = "SELECT * FROM [Car Info] WHERE ? = ?";
comm_database.Connection = conn_database;
OleDbDataAdapter adap_database = new OleDbDataAdapter(comm_database);
DataTable data_database = new DataTable();
for (int i = 0; i < ColumnName.Count; i++)
{
comm_database.Parameters.AddWithValue("?", ColumnName[i].ToString());
comm_database.Parameters.AddWithValue("?", EnteredFields[i].ToString());
MessageBox.Show(adap_database.SelectCommand.CommandText);
adap_database.Fill(data_database);
}
BindingSource bind_database = new BindingSource();
bind_database.DataSource = data_database;
dataGridView1.DataSource = bind_database;
Did you try :
database_command.Parameters.AddWithValue("#x", EnteredFields[i]);
instead of :
database_command.Parameters.AddWithValue("#x", FirstQuery);
Usually when working with parameter you can just add the param name and its value and not have to add the columnName = to the value. Make sense?
One thing that you could try if wanted to leverage using parameters is code below. I don't know if it will solve your problem or not but at least it help protect you from SQL Injection attacks. Please let me know if you have any questions.
string Query = "SELECT * FROM [Car Info] WHERE {0} ";
for (i = 0; i < ColumnName.Count - 1; i++)
{
FirstQuery += string.Format("{0} = #{1} AND ", ColumnName[i], ColumnName[i]);
}
FirstQuery += string.Format("{0} = #{1}", ColumnName[i], ColumnName[i]);
Query = String.Format(Query, FirstQuery);
for (i = 0; i < ColumnName.Count - 1; i++)
{
database_command.Parameters.AddWithValue("#" + ColumnName[i], EnteredFields[i]);
}