ASP.Net C# - Passing a variable into MySQL query - c#

So I want to create a line graph with data from a MySQL table and I've managed to draw one using the code below.
However, I want to pass a variable 'moduleID' to the MySQL query and I have done so, however, I'm not sure if this is the most appropriate way to do so. Should I pass a parameter instead and if so, how do I do that?
protected void chart(int moduleID)
{
string connStr = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
MySqlConnection conn = new MySqlConnection(connStr);
string comm = "SELECT * FROM scores WHERE module_id=" + moduleID.ToString();
MySqlDataAdapter dataAdapter = new MySqlDataAdapter(comm, conn);
DataSet ds = new DataSet();
Chart1.ChartAreas["ChartArea1"].AxisX.MajorGrid.Enabled = false;
Chart1.ChartAreas["ChartArea1"].AxisY.MajorGrid.Enabled = false;
Chart1.ChartAreas["ChartArea1"].AxisX.Minimum = 1;
Chart1.ChartAreas["ChartArea1"].AxisX.LabelStyle.Enabled = false;
Chart1.ChartAreas["ChartArea1"].AxisX.Title = "time";
Chart1.ChartAreas["ChartArea1"].AxisY.Minimum = 0;
Chart1.ChartAreas["ChartArea1"].AxisY.Maximum = 100;
Chart1.ChartAreas["ChartArea1"].AxisY.Title = "%";
Chart1.ChartAreas["ChartArea1"].AxisY.TextOrientation = TextOrientation.Horizontal;
try
{
conn.Open();
dataAdapter.Fill(ds);
Chart1.DataSource = ds;
Chart1.Series["Series1"].YValueMembers = "score";
Chart1.DataBind();
}
catch
{
lblError.Text = "Database connection error. Unable to obtain data at the moment.";
}
finally
{
conn.Close();
}
}

You are right. Concatenating strings to form a query is prone to SQL injection. Use parameters like:
string comm = "SELECT * FROM scores WHERE module_id=#module_id";
MySqlCommand mySqlCommand = new MySqlCommand(comm,conn);
mySqlCommand.Parameters.Add(new MySqlParameter("#module_id", module_id));
MySqlDataAdapter dataAdapter = new MySqlDataAdapter(mySqlCommand);
You should also enclose your connection and command object with using statement. This will ensure proper disposal of resource.
Also an empty catch is very rarely useful. You should catch specific exception first and then the base exception Exception in an object. Use that object to log the exception information or show in your error message. This will provide you help in debugging your application.

Step1: Create stored Procedure
CREATE PROCEDURE SelectScore
(#moduleID NCHAR(50))AS
SELECT * FROM scores WHERE module_id=#moduleID
Step2: Call the stored Procedure from Code
string connStr = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr )) {
conn.Open();
// 1. create a command object identifying the stored procedure
SqlCommand cmd = new SqlCommand("SelectScore", conn);
// 2. set the command object so it knows to execute a stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// 3. add parameter to command, which will be passed to the stored procedure
cmd.Parameters.Add(new SqlParameter("#moduleID ", moduleID ));
// execute the command
using (SqlDataReader rdr = cmd.ExecuteReader()) {
// iterate through results, printing each to console
while (rdr.Read())
{
..
}
}
}

Related

Hello everyone.I want to import values into sql from access database but except previously added records from access

Getting values from my access database into DataTable table
string accessconst = "Provider = Microsoft.Jet.OLEDB.4.0; Data Source = C:/Program Files (x86)/BALLBACH/Database/Messdaten.mdb";
DataTable table = new DataTable();
using (OleDbConnection conn = new OleDbConnection(accessconst))
{
using (OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM Messdaten", conn))
{
da.Fill(table);
}
}
Getting values from my sql database into DataTable tablesql
string sqlconstr = "sqlconstr";
DataTable tablesql = new DataTable();
using (SqlConnection conn = new SqlConnection(sqlconstr))
{
using (SqlDataAdapter da = new SqlDataAdapter("SELECT p1 FROM UMP", conn))
{
da.Fill(tablesql);
}
}
Now I want to import the values into the sql db from the access db except the previously added records from the access db. How can I do this?
//HERE IS THE PROBLEM
using (SqlConnection con = new SqlConnection("MyConnectionStr "))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "INSERT INTO UMP VALUES (#p1, #p2, #p3)";
cmd.Connection = con;
cmd.Parameters.Add("#p1", SqlDbType.NVarChar, 50);
cmd.Parameters.Add("#p2", SqlDbType.NVarChar, 50);
cmd.Parameters.Add("#p3", SqlDbType.NVarChar, 50);
con.Open();
for (int i = 0; i < table.Rows.Count; i++)
{
cmd.Parameters["#p1"].Value = table.Rows[i][0];
cmd.Parameters["#p2"].Value = table.Rows[i][1];
cmd.Parameters["#p3"].Value = table.Rows[i][2];
try
{
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
break;
}
}
}
}
what i would suggest is taking all access data and insert it into a temporary table.
then insert the data based on a left join, perform the insert.
your code would then look something like this...
//data from access
private void insertValues(DataTable table)
{
using (SqlConnection con = new SqlConnection("MyConnectionStr "))
{
using (SqlCommand cmd = con.CreateCommand())
{
createTable();
//note changed the insert to tmp table.
cmd.CommandText = "INSERT INTO UMP_TMP VALUES (#p1, #p2, #p3)";
cmd.Connection = con;
cmd.Parameters.Add("#p1", SqlDbType.NVarChar, 50);
cmd.Parameters.Add("#p2", SqlDbType.NVarChar, 50);
cmd.Parameters.Add("#p3", SqlDbType.NVarChar, 50);
con.Open();
for (int i = 0; i < table.Rows.Count; i++)
{
cmd.Parameters["#p1"].Value = table.Rows[i][0];
cmd.Parameters["#p2"].Value = table.Rows[i][1];
cmd.Parameters["#p3"].Value = table.Rows[i][2];
try
{
cmd.ExecuteNonQuery();
}
catch (Exception)
{
break;
}
}
//merge the data from within sql server
mergeTable();
//drop the temporary table
dropTable();
}
}
}
private void createTable(){
issueStatement("create table UMP_TMP(p1 varchar(50), p2 varchar(50), p3 varchar(50));");
}
private void dropTable()
{
issueStatement("drop table UMP_TMP;");
}
private void mergeTable()
{
issueStatement("insert into UMP select ump_tmp.p1,ump_tmp.p2,ump_tmp.p3 from UMP_TMP left join UMP on UMP_TMP.p1 = UMP.P1 and UMP_TMP.p2 = UMP.P2 and UMP_TMP.p3 = UMP.P3 WHERE ump.p1 is null and ump.p2 is null and ump.p3 is null");
}
private void issueStatement(string command)
{
using (SqlConnection con = new SqlConnection("MyConnectionStr "))
{
using (SqlCommand cmd = con.CreateCommand())
{
con.Open();
cmd.CommandText = command;
//add error handling
cmd.ExecuteNonQuery();
}
}
}
Expanding on #Kirk's response, your ultimate goal that solves the problem is to perform the left join operation on your two tables. You will have needed to identified what columns on each table join the data, and what columns make a row unique.
You can do this in any of the 3 environments your working in a) Access, b) SQL, c) .NET.
I would recommend SQL, its the best at it. (plus your only transferring one set of data through the client (the access data)) So get all the data into SQL tables, and then execute a SQL stored procedure to do the left join and update the SQL data table.
You can work out the SQL work with just Management Studio, the queries etc. Once you've built the stored procedure (and anything else you might need like views). Your .NET code is then two simple parts, 1) upload the Access data 2) call the proc to merge it.
Final point, if your .net's client only purpose is this upload and merge, then you don't need it at all. SQL Servers SSIS can do all of this, and depending on the size of data involved might be the much better choice.

adding to database oledb c#

After searching for about an hour it appears this is the correct way to use the oledb libary to insert a record to an access database however it doesnt work for me , HELP...
InitializeComponent();
System.Data.OleDb.OleDbConnection conn = new
System.Data.OleDb.OleDbConnection();
// TODO: Modify the connection string and include any
// additional required properties for your database.
conn.ConnectionString = #"Provider = Microsoft.ACE.OLEDB.12.0; Data Source = \\crd-a555-015.occ.local\c$\Users\james.piper\Documents\Visual Studio 2015\Projects\Project V1\Project Database.accdb";
try
{
OleDbCommand cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO Work_Done (employee,client,project,task,hours)" + " VALUES (#employee,#client,#project,#task,#hours)";
cmd.Parameters.AddWithValue("#employee", user.employee);
cmd.Parameters.AddWithValue("#client", listBox1.SelectedItem.ToString());
cmd.Parameters.AddWithValue("#project", listBox2.SelectedItem.ToString());
cmd.Parameters.AddWithValue("#task", listBox3.SelectedItem.ToString());
cmd.Parameters.AddWithValue("#hours", listBox4.SelectedItem.ToString());
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show("sql insert fail");
}
I would write this code like this:
var connectionString = #"Provider = Microsoft.ACE.OLEDB.12.0; Data Source = \\crd-a555-015.occ.local\c$\Users\james.piper\Documents\Visual Studio 2015\Projects\Project V1\Project Database.accdb";
var query = "INSERT INTO Work_Done (employee,client,project,task,hours) VALUES (#employee,#client,#project,#task,#hours)";
using (var conn = new OleDbConnection(connectionString))
{
using(var cmd = new OleDbCommand(query, conn))
{
// No need to specifiy command type, since CommandType.Text is the default
// I'm assuming, of course, your parameter data types. You should change them if my assumptions are wrong.
cmd.Parameters.Add("#employee", OleDbType.Integer).Value = user.employee;
cmd.Parameters.Add("#client", OleDbType.Integer).Value = Convert.ToInt32(listBox1.SelectedItem);
cmd.Parameters.Add("#project", OleDbType.Integer).Value = Convert.ToInt32(listBox2.SelectedItem);
cmd.Parameters.Add("#task", OleDbType.Integer).Value = Convert.ToInt32(listBox3.SelectedItem);
cmd.Parameters.Add("#hours", OleDbType.Integer).Value = Convert.ToInt32(listBox4.SelectedItem);
try
{
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show($"sql insert fail: {ex}");
}
}
}
The major changes are these:
use the Using statement for each instance of a class that implements the IDisposable interface.
Using constructors with parameters to make the code shorter (and more readable, IMHO).
Note that the constructor of the OleDbCommand also has the OleDbConnection object. In your code, you didn't specify the active connection to the command.
Adding parameters with Add and not AddWithValue. Read this blog post to find out why.

Integer is being returned as 0 when it shouldn't be. Retrieved from database

I'm trying to get a value from my database but it keeps returning a value of 0 and i cannot figure out why. I've been retrieving data from the database for the whole of my project and it is just not working here. None of the values in the database are = to 0.
int rentalPrice is the one being returned as 0`
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["id"] == null)
{
Response.Redirect("DisplayCars.aspx");
}
else
{
id = Convert.ToInt32(Request.QueryString["id"].ToString());
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select * from cars where id ='" + id + "'";
cmd.ExecuteNonQuery();
lblCarID.Text = id.ToString();
DataTable dt2 = new DataTable();
SqlDataAdapter da2 = new SqlDataAdapter(cmd);
foreach (DataRow dr2 in dt2.Rows)
{
rentalPrice = Convert.ToInt32(dr2["car_rental_price"]);
}
lblRentalPrice.Text = rentalPrice.ToString();
con.Close();
}
// This uses a Connection pool, so you don't need to reuse the same SqlConnection
using (SqlConnection con = new SqlConnection(...))
{
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select [car_rental_price] from cars where id = #Id";
var idParam = new SqlParameter("#Id");
idParam.Value = id;
cmd.Parameters.Add(idParam);
con.Open();
using (var reader = cmd.ExcecuteReader())
{
reader.Read();
lblRentalPrice.Text = reader.GetInt32(0).ToString();
lblCarID.Text = id.ToString();}
}
}
}
To execute a query and get results, you need to use cmd.ExecuteReader.
Also, rather than concatenating values into a string to build your SQL query, you need to use parameterized queries. This helps prevent SQL Injection attacks.
Also, SqlConnection should not be put in a field (class level variable). Instead, you should use local variables and wrap them in a using statement to ensure that they get disposed of properly.
hey you did not fill the Data Table.. then how it has any Values???
first Fill the data Table and use it in Foreach loop
adapter.Fill(DataTable);
foreach(DataRow dr in DataTable)
{
//get the id
}

Get records between two days which are selected by two datetimepickers and fill a datagridview with them in Visual Studio C#

This is my code:
This is in a different class named DBAccess
public DataSet getRecords(DateTime dtpFloor,DateTime dtpCeiling)
{
if (conn.State.ToString() == "Closed")
{
conn.Open();
}
SqlCommand newCmd = conn.CreateCommand();
newCmd.Connection = conn;
newCmd.CommandType = CommandType.Text;
newCmd.CommandText = " SELECT * FROM dbo.ClientInvoice WHERE invDate BETWEEN '" + dtpCeiling + "' AND '" + dtpFloor + "'";
SqlDataAdapter da = new SqlDataAdapter(newCmd);
DataSet dsIncome = new DataSet();
da.Fill(dsIncome, "Client");
conn.Close();
return dsIncome;
}
Below Coding is in the ProfitLos form class
public void btnClickFillGrid()
{
DataSet dsIncome = dba.getRecords(dtpFloor.Value.ToString(), dtpCeiling.Value.ToString()); //dba is an object of DBAccess class
dgvproIncome.DataSource = dsIncome.Tables["Client"].DefaultView;
}
btnClickFillGrid() will invoke at the button click event.
In the database - invdate datetime;(invDate is the variable name and its in the datetime format)
i edited my coding like this
public DataSet getRecords(DateTime dtpFloor,DateTime dtpCeiling)
{
using (SqlConnection conn = new SqlConnection("Data Source=KOSHITHA-PC;Initial Catalog=ITP;Integrated Security=True"))
{
conn.Open();
using (SqlCommand command = conn.CreateCommand())
{
string sql = "SELECT * FROM dbo.ClientInvoice WHERE invDate BETWEEN" + "#from AND #to";
command.CommandText = sql;
command.Parameters.AddWithValue("#from",dtpFloor);
command.Parameters.AddWithValue("#to", dtpCeiling);
SqlDataAdapter da = new SqlDataAdapter(command);
DataSet dataSetClient = new DataSet();
da.Fill(dataSetClient, "Client");
return dataSetClient;
}
}
}
DataSet dataSetClient = dba.getRecords(dtpFloor.Value, dtpCeiling.Value);
dgvproIncome.DataSource = dataSetClient.Tables["Client"].DefaultView;
now i m getting an exception in "da.Fill(dataSetClient, "Client");" line saying
sqlException was unhandled
An expression of non-boolean type specified in a context where a condition is expected, near 'BETWEEN#from'.
i m not familiar with the parameter passing method to sql query,so couldnt find the problem that i m having
Look at this call:
dba.getRecords(dtpFloor.Value.ToString(), dtpCeiling.Value.ToString());
That's clearly passing in strings as the arguments. Now look at your method declaration:
public DataSet getRecords(DateTime dtpFloor,DateTime dtpCeiling)
Those parameters are of type DateTime, not string. So the first thing to fix is the call, to:
dba.getRecords(dtpFloor.Value, dtpCeiling.Value);
Now the next problem is that you're embedding the values in the SQL directly. Don't do that. Never do that. In some cases it can lead to SQL injection attacks, and in other cases it causes data conversion issues (as you've got here). Use parameterized SQL instead - oh, and use connection pooling rather than trying to use a single connection in multiple places:
public DataSet GetRecords(DateTime dtpFloor,DateTime dtpCeiling)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand command = conn.CreateCommand())
{
string sql = "SELECT * FROM dbo.ClientInvoice WHERE invDate BETWEEN "
+ "#from AND #to";
command.CommandText = sql;
command.Parameters.AddWithValue("#from", dtpFloor");
command.Parameters.AddWithValue("#to", dtpCeiling");
SqlDataAdapter da = new SqlDataAdapter(command);
DataSet dataSet = new DataSet();
da.Fill(dataSet, "Client");
return dataSet;
}
}
}

How to call a mySQL stored function in C#?

I'd like to call a stored function in C#. I need articles and some examples for this.
It's almost identical to how you would call a SQL Server Stored Procedure:
using(MySqlConnection conn = new MySqlConnection(connString))
{
MySqlCommand command = new MySqlCommand("spSomeProcedure;", conn);
command.CommandType = System.Data.CommandType.StoredProcedure;
// Add your parameters here if you need them
command.Parameters.Add(new MySqlParameter("someParam", someParamValue));
conn.Open();
int result = (int)command.ExecuteScalar();
}
http://forums.asp.net/p/988462/1278686.aspx
MySqlCommand cmd = new MySqlCommand("DeleteMessage", new MySqlConnection(GetConnectionString()));
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new MySqlParameter("param1", MessageItem.Entry_ID));
cmd.Connection.Open();
int i = cmd.ExecuteNonQuery();
cmd.Connection.Close();
Stored routines
Stored functions and stored procedures are called in different ways.
Stored function is used as regular function in SQL statement.
For example
SELECT id, title, my_function(price) FROM table
Stored procedures are called using CALL statement.
CALL my_procedure(1,2,'title');
I don't know C#, so probably you can use MySqlCommand class to call stored procedures, but you can't use it to call stored functions.
I actually couldn't get the other methods suggested to return a value. I ended up creating a string to call the function and then executed that string with .ExecuteScalar:
MySqlTransaction mySqlTransaction = testDataMySqlConnection.BeginTransaction();
mySqlCommand = new MySqlCommand
{
Connection = testDataMySqlConnection,
CommandText = "SELECT sf_UnitsAttempted('" + ... + ");",
CommandType = CommandType.Text
};
var f = (float)mySqlCommand.ExecuteScalar();
mySqlCommand.Dispose();
return f;
I know the question is about returning from a stored function, and Justin's answer here covers that. I wanted to add that if you wanted to return a DataTable from a stored procedure instead, you can do it using a DataAdapter:
// using MySql.Data.MySqlClient; // remember to include this
/* Helper method that takes in a Dictionary list of parameters,
and returns a DataTable.
The connection string is fetched from a resources file. */
public static DataTable ExecuteProc(string procedureName, Dictionary<string,object> parameterList)
{
DataTable outputDataTable;
using (MySqlConnection MySqlConnection = new MySqlConnection(Resources.SQL_CONNECTION_STRING))
{
using (MySqlCommand sqlCommand = new MySqlCommand(procedureName, MySqlConnection))
{
sqlCommand.CommandType = CommandType.StoredProcedure;
if (parameterList != null)
{
foreach(string key in parameterList.Keys)
{
string parameterName = key;
object parameterValue = parameterList[key];
sqlCommand.Parameters.Add(new MySqlParameter(parameterName, parameterValue));
}
}
MySqlDataAdapter sqlDataAdapter = new MySqlDataAdapter(sqlCommand);
DataSet outputDataSet = new DataSet();
sqlDataAdapter.Fill(outputDataSet, "resultset");
outputDataTable = outputDataSet.Tables["resultset"];
}
}
return outputDataTable;
}

Categories