How can i create a customizable SQL function in Visual Studio - c#

Is it possible to create an extendable SQL query in Visual studio?
private void button1_Click(object sender, EventArgs e)
{
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "Select geneID from Table3 where geneID in(" + filterdata + ")";
cmd.ExecuteNonQuery();
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
dataGridView1.DataSource = dt;
con.Close();
}
Can this be extended to select any possible parameter from any possible tables using any possible conditions. I think it would look something like the following:
Select [Variable 1,Variable 2...] from [Table 1, Table2...] where [Condition1, Condition 2...]
The variables, tables and conditions in this case will be selected using a multitude of checkbox's. I want to incorporate any possible search into one button click.

Use sql joins ..Inside your commenttext like select a.row,b.rowtwo from tableone a inner join tabletwo b on a.row = b.row where a.row = your values

You can use the String.Format method
Converts the value of objects to strings based on the formats specified and inserts them into another string.
If you are new to the String.Format method, see the Getting started with the String.Format method section for a quick overview.
So you can use like that
cmd.CommandText = String.Format("Select {0} from {1} where {2}", columns, tables, conditions)

Related

How do I filter a datagridview with text?

I'm making an application where we can see data from my database in a datagridview. I got to a point that I need to filter somethings and I'm only able to filter with "numbers" for example (IdProducts), this is the code I'm using:
string query= "SELECT * FROM alunos where Estado="+textBox1.Text;
if(a.open_connection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, a.connection);
MySqlDataReader dataReader= cmd.ExecuteReader();
if(dataReader.HasRows)
{
DataTable dt= new DataTable();
dt.Load(dataReader);
dataGridView1.DataSource= dt;
}
dataReader.Close();
a.close_connection();
}
in this code I'm trying to filter the column "Estado" which is text and it gives me this error,
Unknown column 'A' in 'where clause'
"A" is what I'm trying to filter (is a camp from Estado column)
My question is how can I be able to filter with not only numbers but text too?
string query= "SELECT * FROM alunos where Estado="+textBox1.Text;
if(a.open_connection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, a.connection);
MySqlDataReader dataReader= cmd.ExecuteReader();
if(dataReader.HasRows)
{
DataTable dt= new DataTable();
dt.Load(dataReader);
dataGridView1.DataSource= dt;
}
dataReader.Close();
a.close_connection();
}
Yuo need to change your code to use a parameterized query like this
string query= "SELECT * FROM alunos where Estado=#state";
if(a.open_connection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, a.connection);
cmd.Parameters.Add("#state", MySqlDbType.VarChar).Value = textBox1.Text;
MySqlDataReader dataReader= cmd.ExecuteReader();
if(dataReader.HasRows)
{
DataTable dt= new DataTable();
dt.Load(dataReader);
dataGridView1.DataSource= dt;
}
dataReader.Close();
a.close_connection();
}
The problem in your original code is caused by the fact that you concatenate the string value from the textbox without adding quotes around it. In this way the parser is fooled and thinks that you are naming a field and, of course, cannot find it.
However, "resolving" the problem simply adding single quotes around the textbox is not a real solution because you are opening your code to Sql Injection attacks. Instead, if you use a parameterized queries, you don't have your original problem, you avoid sql injection, you will not face other 'syntax errors' caused by the presence of single quotes in your textbox.text property and your database engine can optimize the query because parsing it just one time even if you call it more than one time.

Getting an IndexOutOfRangeException when putting sql into an object array

Currently working on a small tool for the company I am working at which shall handle the database. I have several classes handling various SQL functions, but whenever I try to put specific data from the database into a datagridview I get the Exception.
SQL function:
public class OUsersDB
{
SqlConnection conn = new SqlConnection("Connection Information");
public SqlDataReader Select()
{
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT au.ApplicationId, au.UserId, au.UserName, au.MobileAlias, au.LastActivityDate, au.Name, sms.number, am.email FROM aspnet_users AS au " +
" JOIN aspnet_membership AS am ON au.userid=am.userid " +
" JOIN smsphonebooks AS sms ON au.name=sms.name";
SqlDataReader ur = cmd.ExecuteReader();
return ur;
}
}
Winform datagrid function
public void Usersdb()
{
OUsersDB oudb = new OUsersDB();
SqlDataReader ur = oudb.Select();
myDataUsers.Rows.Clear();
while (ur.Read())
{
object[] objUsers = {
ur["au_ApplicationId"].ToString(),
ur["au_UserId"].ToString(),
ur["au_UserName"].ToString(),
ur["au_MobileAlias"].ToString(),
ur["au_LastActivityDate"].ToString(),
ur["au_Name"].ToString(),
ur["au_Phone"].ToString(),
ur["au_Email"].ToString(), };
myDataUsers.Rows.Add(objUsers);
conn.Close();
}
I have a similar sql function and object array futher up in the code which loads just fine, but once reaching this part I get the Exception on the
ur["au_ApplicationId"].ToString(),
It simply says
System.IndexOutOfRangeException: 'au_ApplicationId'
Change the obj to read the columns without the alias. You use aliases only to reference the columns in the query, but the output of the query won't have the aliases.
while (ur.Read())
{
object[] objUsers = {
ur["ApplicationId"].ToString(),
ur["UserId"].ToString(),
ur["UserName"].ToString(),
ur["MobileAlias"].ToString(),
ur["LastActivityDate"].ToString(),
ur["Name"].ToString(),
ur["Phone"].ToString(),
ur["Email"].ToString(), };
myDataUsers.Rows.Add(objUsers);
conn.Close();
}
Check if you get ANY object, maybe you get nothing at all.
You can try this:
https://stackoverflow.com/a/8656011/8512753
or remove the table aliases
ur["au_ApplicationId"].ToString(),
becomes
ur["ApplicationId"].ToString(),
and try assigning concrete values to the columns returned in your SQL
SELECT ApplicationId = au.ApplicationId, ...
Regarding the IndexOutOfRangeException, that's due to trying to access a column that doesn't exist in the reader. Not sure why you're prefixing columns with "au_" when the SELECT statement is not doing this.
I would use SqlDataAdapter instead and add add this method to OUsersDB.
public void FillTable(DataTable table)
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT au.ApplicationId, au.UserId, au.UserName, au.MobileAlias, au.LastActivityDate, au.Name, sms.number, am.email FROM aspnet_users AS au " +
" JOIN aspnet_membership AS am ON au.userid=am.userid " +
" JOIN smsphonebooks AS sms ON au.name=sms.name";
using(var adapter = new SqlDataAdapter(cmd))
adapter.Fill(table)
}
Change calling code to:
public void Usersdb()
{
OUsersDB oudb = new OUsersDB();
myDataUsers.Rows.Clear();
oudb.FillTable(myDataUsers);
}
Or here's a simple fix, instead. Change your SELECT statement to alias column names as the code is expecting.
SELECT au.ApplicationId as au_ApplicationId, au.UserId as au_UserId, au.UserName as au_UserName,
au.MobileAlias as au_MobileAlias, au.LastActivityDate as au_LastActivity, au.Name as au_Name,
sms.number as au_Phone, am.email as au_Email -- REST OF QUERY UNCHANGED

How to add to an Update statement

I am trying to update my database(Table) and make the active column = 1.
I have duplicate reports (subject_text) with different countries and parameters.
subject_text countries parameter1 active
usage GB 1 0
usage FR 2 0
usage PT 1 0
closed GB,FR,PT 1 0
Here is an example of what my database looks like(simplified, there are many more parameters and many more reports but i hope you can see what I mean by duplicate report names)
Here is my .cs file to show the update i am trying to carry out.The Subject_text are in drop-down list form so the user can select which report to update. These reports(subject_text) are hard-coded into my ASPX page. When selecting a report such as 'closed' the update works, but when it comes to updating reports which have different countries or parameters that where i'm having trouble.
Masterpage masteris linking this page to where the .getDropDownListValue is
How can I add to my update statement when the drop-down lists contain different elements?
protected void RunReport_Click (object sender, System.EventArgs e)
{
MasterPage master = (MasterPage)this.Master;
string sqlStatement = "";
sqlStatement = #"UPDATE [TODD].[dbo].[Table] SET Active='1' WHERE subject_text = #report";
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(sqlStatement, conn);
cmd = new SqlCommand(sqlStatement, conn);
cmd.Parameters.AddWithValue("#report", ddl_Report.SelectedItem.Text);
string getcountry = master.getDropDownListValue(ddl_country, false);
if (!string.IsNullOrWhiteSpace(getcountry))
{
cmd.Parameters.AddWithValue("#country", getcountry);
sqlStatement += "AND countries = #country";
}
string getparam1 = master.getDropDownListValue(Param1, false);
if (!string.IsNullOrWhiteSpace(getparam1))
{
cmd.Parameters.AddWithValue("#param1", getparam1);
sqlStatement += "AND parameter1 = #param1";
}
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
Thank you for your time.
move
SqlCommand cmd = new SqlCommand(sqlStatement, conn);
to below the final calculation of your string sqlStatement
adding new text to sqlStatement should be done before you create your SqlCommand based on sqlStatement
also, you do not need to call new SqlCommand(sqlStatement, conn); twice
Why don't you just pass the identity? This is much cleaner.
UPDATE [TODD].[dbo].[Table] SET Active='1' WHERE RecordID = #RecordId

C# No value given for 1 or more required parameters, but I can't see why

I have posted the code I have below
I am trying to get the data from an Access 2002-2003 database
If I take out everything after the WHERE clause and just use "SELECT * FROM [{0}] then it takes all the data from the table with no problems. I have double checked the field names, they are definitely correct. I have more than 1 table with the same field names, so I thought maybe I would need to include the table name before the field name, but with or without the table I still get the same exception. I have tried moving the position of the square brackets, again with no success...
Even if I include only one of the WHERE clauses, the code no longer works, and I can't for the life of me work out why.. I have spent hours looking at numerous posts here and on other sites related to this error, but none of the suggestions have helped me..
The Destination field is a 'memo' field in Access.
The Next Collection fields are date fields, GVars.currentDate is set earlier in the code to be today's date (with the time portion set to 00:00:00).
GVars.thisFY is also set programatically as a string prior to this.
Any tips would be appreciated.
string sql;
OleDbDataAdapter adapter;
sql = string.Format(
"SELECT * FROM [{0}] WHERE {0}.[Destination] = #Destination AND {0}.[Next Collection] BETWEEN #NextCollectionA AND #NextCollectionB"
, GVars.thisFY);
// Create the command object
OleDbCommand cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = sql;
// Add values to the fields
cmd.Parameters.AddWithValue("#Destination", "Henwood");
cmd.Parameters.AddWithValue("#NextCollectionA", GVars.currentDate);
cmd.Parameters.AddWithValue("#NextCollectionB", GVars.currentDate.AddDays(1));
adapter = new OleDbDataAdapter(cmd.CommandText, conn);
System.Diagnostics.Debug.Print(cmd.CommandText);
try
{
adapter.Fill(ds);
GVars.bLblLastUpdate = DateTime.Now.ToString("HH:mm:ss");
}
catch (Exception ex)
{
}
EDIT:
Thanks Vladislav for the answer, corrected code posted below:
string sql;
OleDbDataAdapter adapter;
sql = string.Format(
"SELECT * FROM [{0}] WHERE [{0}].[Destination] = #Destination AND [{0}].[Next Collection] BETWEEN #NextCollectionA AND #NextCollectionB"
, GVars.thisFY);
// Create the command object
OleDbCommand cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = sql;
cmd.Connection = conn;
// Add values to the fields
cmd.Parameters.Add("#Destination", OleDbType.Char).Value = "Henwood";
cmd.Parameters.Add("#NextCollectionA", OleDbType.DBDate).Value = GVars.currentDate;
cmd.Parameters.Add("#NextCollectionB", OleDbType.DBDate).Value = GVars.currentDate.AddDays(1);
adapter = new OleDbDataAdapter(cmd);
try
{
adapter.Fill(ds);
GVars.bLblLastUpdate = DateTime.Now.ToString("HH:mm:ss");
}
Try to specify types for the parameters you add.
Another thing I notice is that to your adapter you are passing only the CommandText.
You should pass the whole command object.

Select value from database based on dropdownlist value

I have database table leave_rec(name,date1,leave,ltype), a Dropdown list and a gridview.
I want to do such that,when I select month(e.g. february) in dropdown list the gridview should display all table values for february only(e.g.rohan leuva,2/28/2013,full,casual),means record which has month=2 (february).
How to overcome this issue? I tried but I can only display all the values in gridview at this moment. Any help would be greatly appriciated.
SqlConnection conn = new SqlConnection();
conn.ConnectionString=System.Configuration.ConfigurationManager.ConnectionStrings["leave"].ConnectionString;
conn.Open();
SqlCommand cmd = new SqlCommand("select date1,leave,ltype from leave_rec where name='" + DropDownList1.SelectedValue + "'", conn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
GridView1.DataSource = ds;
GridView1.DataBind();
The above code displays the date1,leave,ltype for dropdownlist1.selectedvalue. But now i want to have second dropdown in which months will be there. so when i select february in second one, grid should display value for dropdownlist1.selectedvalue for february only.
First, your query needs to be something like this:
select date1, leave, ltype from leave_rec where MONTH(date1) = 2 // February
Then, integrating it into your code:
SqlCommand cmd = new SqlCommand("select date1, leave, ltype from leave_rec where MONTH(date1) = #p1", conn);
cmd.Parameters.Add(new SqlParameter("p1", combo.SelectedKey));
Use parameters instead of string concatenation to avoid SQL Injection, see an example here: http://www.dotnetperls.com/sqlparameter
(Use your own control names for "combo.SelectedKey", of course)
I think problem in query , instead of name you have to write date1
SqlCommand cmd = new SqlCommand("select date1, leave, ltype from leave_rec where MONTH(date1) ='" + DropDownList1.SelectedValue + "'", conn);
Convert the dataset to DataTable
then - Filter it by dt.Filter=monthName.toString()
then bind it to GridView - dt.DefaultView;
Agree with #Saurabh, look into the use of Linq and Stored Procedures to force the use of types and modelling.

Categories

Resources